xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp (revision 6c4b055cfb6bf549e9145dde6454cc6b178c35e4)
10b57cec5SDimitry Andric //===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "Darwin.h"
10e8d8bef9SDimitry Andric #include "Arch/AArch64.h"
110b57cec5SDimitry Andric #include "Arch/ARM.h"
120b57cec5SDimitry Andric #include "CommonArgs.h"
130b57cec5SDimitry Andric #include "clang/Basic/AlignedAllocation.h"
140b57cec5SDimitry Andric #include "clang/Basic/ObjCRuntime.h"
150b57cec5SDimitry Andric #include "clang/Config/config.h"
160b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
170b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
180b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
190b57cec5SDimitry Andric #include "clang/Driver/Options.h"
200b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
220b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
23480093f4SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
240b57cec5SDimitry Andric #include "llvm/Support/Path.h"
250b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
265ffd83dbSDimitry Andric #include "llvm/Support/Threading.h"
270b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
2806c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h"
2906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
300b57cec5SDimitry Andric #include <cstdlib> // ::getenv
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace clang::driver;
330b57cec5SDimitry Andric using namespace clang::driver::tools;
340b57cec5SDimitry Andric using namespace clang::driver::toolchains;
350b57cec5SDimitry Andric using namespace clang;
360b57cec5SDimitry Andric using namespace llvm::opt;
370b57cec5SDimitry Andric 
38349cc55cSDimitry Andric static VersionTuple minimumMacCatalystDeploymentTarget() {
39fe6060f1SDimitry Andric   return VersionTuple(13, 1);
40fe6060f1SDimitry Andric }
41fe6060f1SDimitry Andric 
420b57cec5SDimitry Andric llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
430b57cec5SDimitry Andric   // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
440b57cec5SDimitry Andric   // archs which Darwin doesn't use.
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   // The matching this routine does is fairly pointless, since it is neither the
470b57cec5SDimitry Andric   // complete architecture list, nor a reasonable subset. The problem is that
48bdd1243dSDimitry Andric   // historically the driver accepts this and also ties its -march=
490b57cec5SDimitry Andric   // handling to the architecture name, so we need to be careful before removing
500b57cec5SDimitry Andric   // support for it.
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   // This code must be kept in sync with Clang's Darwin specific argument
530b57cec5SDimitry Andric   // translation.
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
560b57cec5SDimitry Andric       .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
570b57cec5SDimitry Andric       .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
580b57cec5SDimitry Andric              llvm::Triple::x86)
590b57cec5SDimitry Andric       .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
60bdd1243dSDimitry Andric       // This is derived from the driver.
610b57cec5SDimitry Andric       .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
620b57cec5SDimitry Andric       .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
630b57cec5SDimitry Andric       .Cases("armv7s", "xscale", llvm::Triple::arm)
64e8d8bef9SDimitry Andric       .Cases("arm64", "arm64e", llvm::Triple::aarch64)
65480093f4SDimitry Andric       .Case("arm64_32", llvm::Triple::aarch64_32)
660b57cec5SDimitry Andric       .Case("r600", llvm::Triple::r600)
670b57cec5SDimitry Andric       .Case("amdgcn", llvm::Triple::amdgcn)
680b57cec5SDimitry Andric       .Case("nvptx", llvm::Triple::nvptx)
690b57cec5SDimitry Andric       .Case("nvptx64", llvm::Triple::nvptx64)
700b57cec5SDimitry Andric       .Case("amdil", llvm::Triple::amdil)
710b57cec5SDimitry Andric       .Case("spir", llvm::Triple::spir)
720b57cec5SDimitry Andric       .Default(llvm::Triple::UnknownArch);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
7506c3fb27SDimitry Andric void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,
7606c3fb27SDimitry Andric                                            const ArgList &Args) {
770b57cec5SDimitry Andric   const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
780b57cec5SDimitry Andric   llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
790b57cec5SDimitry Andric   T.setArch(Arch);
80fe6060f1SDimitry Andric   if (Arch != llvm::Triple::UnknownArch)
810b57cec5SDimitry Andric     T.setArchName(Str);
82fe6060f1SDimitry Andric 
83fe6060f1SDimitry Andric   if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
840b57cec5SDimitry Andric       ArchKind == llvm::ARM::ArchKind::ARMV7M ||
850b57cec5SDimitry Andric       ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
8606c3fb27SDimitry Andric     // Don't reject these -version-min= if we have the appropriate triple.
8706c3fb27SDimitry Andric     if (T.getOS() == llvm::Triple::IOS)
8806c3fb27SDimitry Andric       for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ))
8906c3fb27SDimitry Andric         A->ignoreTargetSpecific();
9006c3fb27SDimitry Andric     if (T.getOS() == llvm::Triple::WatchOS)
9106c3fb27SDimitry Andric       for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))
9206c3fb27SDimitry Andric         A->ignoreTargetSpecific();
9306c3fb27SDimitry Andric     if (T.getOS() == llvm::Triple::TvOS)
9406c3fb27SDimitry Andric       for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))
9506c3fb27SDimitry Andric         A->ignoreTargetSpecific();
9606c3fb27SDimitry Andric 
970b57cec5SDimitry Andric     T.setOS(llvm::Triple::UnknownOS);
980b57cec5SDimitry Andric     T.setObjectFormat(llvm::Triple::MachO);
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
1030b57cec5SDimitry Andric                                      const InputInfo &Output,
1040b57cec5SDimitry Andric                                      const InputInfoList &Inputs,
1050b57cec5SDimitry Andric                                      const ArgList &Args,
1060b57cec5SDimitry Andric                                      const char *LinkingOutput) const {
107349cc55cSDimitry Andric   const llvm::Triple &T(getToolChain().getTriple());
108349cc55cSDimitry Andric 
1090b57cec5SDimitry Andric   ArgStringList CmdArgs;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   assert(Inputs.size() == 1 && "Unexpected number of inputs.");
1120b57cec5SDimitry Andric   const InputInfo &Input = Inputs[0];
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   // Determine the original source input.
1150b57cec5SDimitry Andric   const Action *SourceAction = &JA;
1160b57cec5SDimitry Andric   while (SourceAction->getKind() != Action::InputClass) {
1170b57cec5SDimitry Andric     assert(!SourceAction->getInputs().empty() && "unexpected root action!");
1180b57cec5SDimitry Andric     SourceAction = SourceAction->getInputs()[0];
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
1220b57cec5SDimitry Andric   // sure it runs its system assembler not clang's integrated assembler.
1230b57cec5SDimitry Andric   // Applicable to darwin11+ and Xcode 4+.  darwin<10 lacked integrated-as.
1240b57cec5SDimitry Andric   // FIXME: at run-time detect assembler capabilities or rely on version
1250b57cec5SDimitry Andric   // information forwarded by -target-assembler-version.
1260b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_fno_integrated_as)) {
1270b57cec5SDimitry Andric     if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
1280b57cec5SDimitry Andric       CmdArgs.push_back("-Q");
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   // Forward -g, assuming we are dealing with an actual assembly file.
1320b57cec5SDimitry Andric   if (SourceAction->getType() == types::TY_Asm ||
1330b57cec5SDimitry Andric       SourceAction->getType() == types::TY_PP_Asm) {
1340b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_gstabs))
1350b57cec5SDimitry Andric       CmdArgs.push_back("--gstabs");
1360b57cec5SDimitry Andric     else if (Args.hasArg(options::OPT_g_Group))
1370b57cec5SDimitry Andric       CmdArgs.push_back("-g");
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   // Derived from asm spec.
1410b57cec5SDimitry Andric   AddMachOArch(Args, CmdArgs);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   // Use -force_cpusubtype_ALL on x86 by default.
144349cc55cSDimitry Andric   if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))
1450b57cec5SDimitry Andric     CmdArgs.push_back("-force_cpusubtype_ALL");
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   if (getToolChain().getArch() != llvm::Triple::x86_64 &&
1480b57cec5SDimitry Andric       (((Args.hasArg(options::OPT_mkernel) ||
1490b57cec5SDimitry Andric          Args.hasArg(options::OPT_fapple_kext)) &&
1500b57cec5SDimitry Andric         getMachOToolChain().isKernelStatic()) ||
1510b57cec5SDimitry Andric        Args.hasArg(options::OPT_static)))
1520b57cec5SDimitry Andric     CmdArgs.push_back("-static");
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   assert(Output.isFilename() && "Unexpected lipo output.");
1570b57cec5SDimitry Andric   CmdArgs.push_back("-o");
1580b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   assert(Input.isFilename() && "Invalid input.");
1610b57cec5SDimitry Andric   CmdArgs.push_back(Input.getFilename());
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   // asm_final spec is empty.
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
1665ffd83dbSDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
167e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric void darwin::MachOTool::anchor() {}
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric void darwin::MachOTool::AddMachOArch(const ArgList &Args,
1730b57cec5SDimitry Andric                                      ArgStringList &CmdArgs) const {
1740b57cec5SDimitry Andric   StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   // Derived from darwin_arch spec.
1770b57cec5SDimitry Andric   CmdArgs.push_back("-arch");
1780b57cec5SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(ArchName));
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // FIXME: Is this needed anymore?
1810b57cec5SDimitry Andric   if (ArchName == "arm")
1820b57cec5SDimitry Andric     CmdArgs.push_back("-force_cpusubtype_ALL");
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
1860b57cec5SDimitry Andric   // We only need to generate a temp path for LTO if we aren't compiling object
1870b57cec5SDimitry Andric   // files. When compiling source files, we run 'dsymutil' after linking. We
1880b57cec5SDimitry Andric   // don't run 'dsymutil' when compiling object files.
1890b57cec5SDimitry Andric   for (const auto &Input : Inputs)
1900b57cec5SDimitry Andric     if (Input.getType() != types::TY_Object)
1910b57cec5SDimitry Andric       return true;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   return false;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric /// Pass -no_deduplicate to ld64 under certain conditions:
1970b57cec5SDimitry Andric ///
1980b57cec5SDimitry Andric /// - Either -O0 or -O1 is explicitly specified
1990b57cec5SDimitry Andric /// - No -O option is specified *and* this is a compile+link (implicit -O0)
2000b57cec5SDimitry Andric ///
2010b57cec5SDimitry Andric /// Also do *not* add -no_deduplicate when no -O option is specified and this
2020b57cec5SDimitry Andric /// is just a link (we can't imply -O0)
2030b57cec5SDimitry Andric static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
2040b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
2050b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_O0))
2060b57cec5SDimitry Andric       return true;
2070b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_O))
2080b57cec5SDimitry Andric       return llvm::StringSwitch<bool>(A->getValue())
2090b57cec5SDimitry Andric                     .Case("1", true)
2100b57cec5SDimitry Andric                     .Default(false);
2110b57cec5SDimitry Andric     return false; // OPT_Ofast & OPT_O4
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
2150b57cec5SDimitry Andric     return true;
2160b57cec5SDimitry Andric   return false;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
2200b57cec5SDimitry Andric                                  ArgStringList &CmdArgs,
2215ffd83dbSDimitry Andric                                  const InputInfoList &Inputs,
2227a6dacacSDimitry Andric                                  VersionTuple Version, bool LinkerIsLLD,
2237a6dacacSDimitry Andric                                  bool UsePlatformVersion) const {
2240b57cec5SDimitry Andric   const Driver &D = getToolChain().getDriver();
2250b57cec5SDimitry Andric   const toolchains::MachO &MachOTC = getMachOToolChain();
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   // Newer linkers support -demangle. Pass it if supported and not disabled by
2280b57cec5SDimitry Andric   // the user.
22981ad6265SDimitry Andric   if ((Version >= VersionTuple(100) || LinkerIsLLD) &&
230e8d8bef9SDimitry Andric       !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
2310b57cec5SDimitry Andric     CmdArgs.push_back("-demangle");
2320b57cec5SDimitry Andric 
23381ad6265SDimitry Andric   if (Args.hasArg(options::OPT_rdynamic) &&
23481ad6265SDimitry Andric       (Version >= VersionTuple(137) || LinkerIsLLD))
2350b57cec5SDimitry Andric     CmdArgs.push_back("-export_dynamic");
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   // If we are using App Extension restrictions, pass a flag to the linker
2380b57cec5SDimitry Andric   // telling it that the compiled code has been audited.
2390b57cec5SDimitry Andric   if (Args.hasFlag(options::OPT_fapplication_extension,
2400b57cec5SDimitry Andric                    options::OPT_fno_application_extension, false))
2410b57cec5SDimitry Andric     CmdArgs.push_back("-application_extension");
2420b57cec5SDimitry Andric 
24381ad6265SDimitry Andric   if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&
24481ad6265SDimitry Andric       NeedsTempPath(Inputs)) {
2450b57cec5SDimitry Andric     std::string TmpPathName;
2460b57cec5SDimitry Andric     if (D.getLTOMode() == LTOK_Full) {
2470b57cec5SDimitry Andric       // If we are using full LTO, then automatically create a temporary file
2480b57cec5SDimitry Andric       // path for the linker to use, so that it's lifetime will extend past a
2490b57cec5SDimitry Andric       // possible dsymutil step.
2500b57cec5SDimitry Andric       TmpPathName =
2510b57cec5SDimitry Andric           D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
2520b57cec5SDimitry Andric     } else if (D.getLTOMode() == LTOK_Thin)
2530b57cec5SDimitry Andric       // If we are using thin LTO, then create a directory instead.
2540b57cec5SDimitry Andric       TmpPathName = D.GetTemporaryDirectory("thinlto");
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric     if (!TmpPathName.empty()) {
2570b57cec5SDimitry Andric       auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
2580b57cec5SDimitry Andric       C.addTempFile(TmpPath);
2590b57cec5SDimitry Andric       CmdArgs.push_back("-object_path_lto");
2600b57cec5SDimitry Andric       CmdArgs.push_back(TmpPath);
2610b57cec5SDimitry Andric     }
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   // Use -lto_library option to specify the libLTO.dylib path. Try to find
2650b57cec5SDimitry Andric   // it in clang installed libraries. ld64 will only look at this argument
2660b57cec5SDimitry Andric   // when it actually uses LTO, so libLTO.dylib only needs to exist at link
2670b57cec5SDimitry Andric   // time if ld64 decides that it needs to use LTO.
2680b57cec5SDimitry Andric   // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
2690b57cec5SDimitry Andric   // next to it. That's ok since ld64 using a libLTO.dylib not matching the
2700b57cec5SDimitry Andric   // clang version won't work anyways.
271e8d8bef9SDimitry Andric   // lld is built at the same revision as clang and statically links in
272e8d8bef9SDimitry Andric   // LLVM libraries, so it doesn't need libLTO.dylib.
27381ad6265SDimitry Andric   if (Version >= VersionTuple(133) && !LinkerIsLLD) {
2740b57cec5SDimitry Andric     // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
2750b57cec5SDimitry Andric     StringRef P = llvm::sys::path::parent_path(D.Dir);
2760b57cec5SDimitry Andric     SmallString<128> LibLTOPath(P);
2770b57cec5SDimitry Andric     llvm::sys::path::append(LibLTOPath, "lib");
2780b57cec5SDimitry Andric     llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
2790b57cec5SDimitry Andric     CmdArgs.push_back("-lto_library");
2800b57cec5SDimitry Andric     CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric 
28381ad6265SDimitry Andric   // ld64 version 262 and above runs the deduplicate pass by default.
28481ad6265SDimitry Andric   // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`
28581ad6265SDimitry Andric   //        if `!shouldLinkerNotDedup()` if LinkerIsLLD here?
28681ad6265SDimitry Andric   if (Version >= VersionTuple(262) &&
28781ad6265SDimitry Andric       shouldLinkerNotDedup(C.getJobs().empty(), Args))
2880b57cec5SDimitry Andric     CmdArgs.push_back("-no_deduplicate");
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   // Derived from the "link" spec.
2910b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_static);
2920b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_static))
2930b57cec5SDimitry Andric     CmdArgs.push_back("-dynamic");
2940b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_fgnu_runtime)) {
2950b57cec5SDimitry Andric     // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
2960b57cec5SDimitry Andric     // here. How do we wish to handle such things?
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_dynamiclib)) {
3000b57cec5SDimitry Andric     AddMachOArch(Args, CmdArgs);
3010b57cec5SDimitry Andric     // FIXME: Why do this only on this path?
3020b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_bundle);
3050b57cec5SDimitry Andric     Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
3060b57cec5SDimitry Andric     Args.AddAllArgs(CmdArgs, options::OPT_client__name);
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric     Arg *A;
3090b57cec5SDimitry Andric     if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
3100b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_current__version)) ||
3110b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_install__name)))
3120b57cec5SDimitry Andric       D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
3130b57cec5SDimitry Andric                                                        << "-dynamiclib";
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
3160b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
3170b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
3180b57cec5SDimitry Andric   } else {
3190b57cec5SDimitry Andric     CmdArgs.push_back("-dylib");
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric     Arg *A;
3220b57cec5SDimitry Andric     if ((A = Args.getLastArg(options::OPT_bundle)) ||
3230b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_bundle__loader)) ||
3240b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_client__name)) ||
3250b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
3260b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
3270b57cec5SDimitry Andric         (A = Args.getLastArg(options::OPT_private__bundle)))
3280b57cec5SDimitry Andric       D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
3290b57cec5SDimitry Andric                                                       << "-dynamiclib";
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric     Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
3320b57cec5SDimitry Andric                               "-dylib_compatibility_version");
3330b57cec5SDimitry Andric     Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
3340b57cec5SDimitry Andric                               "-dylib_current_version");
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     AddMachOArch(Args, CmdArgs);
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
3390b57cec5SDimitry Andric                               "-dylib_install_name");
3400b57cec5SDimitry Andric   }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_all__load);
3430b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
3440b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
3450b57cec5SDimitry Andric   if (MachOTC.isTargetIOSBased())
3460b57cec5SDimitry Andric     Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
3470b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
3480b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
3490b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
3500b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_dynamic);
3510b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
3520b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
3530b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_force__load);
3540b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
3550b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_image__base);
3560b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_init);
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   // Add the deployment target.
3597a6dacacSDimitry Andric   if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)
360480093f4SDimitry Andric     MachOTC.addPlatformVersionArgs(Args, CmdArgs);
361480093f4SDimitry Andric   else
3620b57cec5SDimitry Andric     MachOTC.addMinVersionArgs(Args, CmdArgs);
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
3650b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_multi__module);
3660b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_single__module);
3670b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
3680b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   if (const Arg *A =
3710b57cec5SDimitry Andric           Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
3720b57cec5SDimitry Andric                           options::OPT_fno_pie, options::OPT_fno_PIE)) {
3730b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_fpie) ||
3740b57cec5SDimitry Andric         A->getOption().matches(options::OPT_fPIE))
3750b57cec5SDimitry Andric       CmdArgs.push_back("-pie");
3760b57cec5SDimitry Andric     else
3770b57cec5SDimitry Andric       CmdArgs.push_back("-no_pie");
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   // for embed-bitcode, use -bitcode_bundle in linker command
3810b57cec5SDimitry Andric   if (C.getDriver().embedBitcodeEnabled()) {
3820b57cec5SDimitry Andric     // Check if the toolchain supports bitcode build flow.
3830b57cec5SDimitry Andric     if (MachOTC.SupportsEmbeddedBitcode()) {
3840b57cec5SDimitry Andric       CmdArgs.push_back("-bitcode_bundle");
38581ad6265SDimitry Andric       // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.
38681ad6265SDimitry Andric       if (C.getDriver().embedBitcodeMarkerOnly() &&
38781ad6265SDimitry Andric           Version >= VersionTuple(278)) {
3880b57cec5SDimitry Andric         CmdArgs.push_back("-bitcode_process_mode");
3890b57cec5SDimitry Andric         CmdArgs.push_back("marker");
3900b57cec5SDimitry Andric       }
3910b57cec5SDimitry Andric     } else
3920b57cec5SDimitry Andric       D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
3930b57cec5SDimitry Andric   }
3940b57cec5SDimitry Andric 
395fe6060f1SDimitry Andric   // If GlobalISel is enabled, pass it through to LLVM.
396fe6060f1SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
397fe6060f1SDimitry Andric                                options::OPT_fno_global_isel)) {
398fe6060f1SDimitry Andric     if (A->getOption().matches(options::OPT_fglobal_isel)) {
399fe6060f1SDimitry Andric       CmdArgs.push_back("-mllvm");
400fe6060f1SDimitry Andric       CmdArgs.push_back("-global-isel");
401fe6060f1SDimitry Andric       // Disable abort and fall back to SDAG silently.
402fe6060f1SDimitry Andric       CmdArgs.push_back("-mllvm");
403fe6060f1SDimitry Andric       CmdArgs.push_back("-global-isel-abort=0");
404fe6060f1SDimitry Andric     }
405fe6060f1SDimitry Andric   }
406fe6060f1SDimitry Andric 
40706c3fb27SDimitry Andric   if (Args.hasArg(options::OPT_mkernel) ||
40806c3fb27SDimitry Andric       Args.hasArg(options::OPT_fapple_kext) ||
40906c3fb27SDimitry Andric       Args.hasArg(options::OPT_ffreestanding)) {
41006c3fb27SDimitry Andric     CmdArgs.push_back("-mllvm");
41106c3fb27SDimitry Andric     CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");
41206c3fb27SDimitry Andric   }
41306c3fb27SDimitry Andric 
4140b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_prebind);
4150b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_noprebind);
4160b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
4170b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
4180b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
4190b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
4200b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
4210b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
4220b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_segprot);
4230b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
4240b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
4250b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
4260b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
4270b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
4280b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
4290b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   // Give --sysroot= preference, over the Apple specific behavior to also use
4320b57cec5SDimitry Andric   // --isysroot as the syslibroot.
4330b57cec5SDimitry Andric   StringRef sysroot = C.getSysRoot();
4340b57cec5SDimitry Andric   if (sysroot != "") {
4350b57cec5SDimitry Andric     CmdArgs.push_back("-syslibroot");
4360b57cec5SDimitry Andric     CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
4370b57cec5SDimitry Andric   } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
4380b57cec5SDimitry Andric     CmdArgs.push_back("-syslibroot");
4390b57cec5SDimitry Andric     CmdArgs.push_back(A->getValue());
4400b57cec5SDimitry Andric   }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
4430b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
4440b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
4450b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_undefined);
4460b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
4470b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
4480b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
4490b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_y);
4500b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_w);
4510b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
4520b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
4530b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
4540b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
4550b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
4560b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
4570b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
458fe6060f1SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_why_load);
4590b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
4600b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
4610b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_dylinker);
4620b57cec5SDimitry Andric   Args.AddLastArg(CmdArgs, options::OPT_Mach);
46306c3fb27SDimitry Andric 
46406c3fb27SDimitry Andric   if (LinkerIsLLD) {
46506c3fb27SDimitry Andric     if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
46606c3fb27SDimitry Andric       SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0
46706c3fb27SDimitry Andric                                 ? ""
46806c3fb27SDimitry Andric                                 : CSPGOGenerateArg->getValue());
46906c3fb27SDimitry Andric       llvm::sys::path::append(Path, "default_%m.profraw");
47006c3fb27SDimitry Andric       CmdArgs.push_back("--cs-profile-generate");
47106c3fb27SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
47206c3fb27SDimitry Andric     } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
47306c3fb27SDimitry Andric       SmallString<128> Path(
47406c3fb27SDimitry Andric           ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
47506c3fb27SDimitry Andric       if (Path.empty() || llvm::sys::fs::is_directory(Path))
47606c3fb27SDimitry Andric         llvm::sys::path::append(Path, "default.profdata");
47706c3fb27SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
47806c3fb27SDimitry Andric     }
47906c3fb27SDimitry Andric   }
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric /// Determine whether we are linking the ObjC runtime.
4830b57cec5SDimitry Andric static bool isObjCRuntimeLinked(const ArgList &Args) {
4840b57cec5SDimitry Andric   if (isObjCAutoRefCount(Args)) {
4850b57cec5SDimitry Andric     Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
4860b57cec5SDimitry Andric     return true;
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric   return Args.hasArg(options::OPT_fobjc_link_runtime);
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
4915ffd83dbSDimitry Andric static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
4925ffd83dbSDimitry Andric                                 const llvm::Triple &Triple) {
4935ffd83dbSDimitry Andric   // When enabling remarks, we need to error if:
4945ffd83dbSDimitry Andric   // * The remark file is specified but we're targeting multiple architectures,
4955ffd83dbSDimitry Andric   // which means more than one remark file is being generated.
4965ffd83dbSDimitry Andric   bool hasMultipleInvocations =
4975ffd83dbSDimitry Andric       Args.getAllArgValues(options::OPT_arch).size() > 1;
4985ffd83dbSDimitry Andric   bool hasExplicitOutputFile =
4995ffd83dbSDimitry Andric       Args.getLastArg(options::OPT_foptimization_record_file_EQ);
5005ffd83dbSDimitry Andric   if (hasMultipleInvocations && hasExplicitOutputFile) {
5015ffd83dbSDimitry Andric     D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
5025ffd83dbSDimitry Andric         << "-foptimization-record-file";
5035ffd83dbSDimitry Andric     return false;
5045ffd83dbSDimitry Andric   }
5055ffd83dbSDimitry Andric   return true;
5065ffd83dbSDimitry Andric }
5075ffd83dbSDimitry Andric 
5085ffd83dbSDimitry Andric static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
5095ffd83dbSDimitry Andric                                  const llvm::Triple &Triple,
5105ffd83dbSDimitry Andric                                  const InputInfo &Output, const JobAction &JA) {
5115ffd83dbSDimitry Andric   StringRef Format = "yaml";
5125ffd83dbSDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
5135ffd83dbSDimitry Andric     Format = A->getValue();
5145ffd83dbSDimitry Andric 
5155ffd83dbSDimitry Andric   CmdArgs.push_back("-mllvm");
5165ffd83dbSDimitry Andric   CmdArgs.push_back("-lto-pass-remarks-output");
5175ffd83dbSDimitry Andric   CmdArgs.push_back("-mllvm");
5185ffd83dbSDimitry Andric 
5195ffd83dbSDimitry Andric   const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
5205ffd83dbSDimitry Andric   if (A) {
5215ffd83dbSDimitry Andric     CmdArgs.push_back(A->getValue());
5225ffd83dbSDimitry Andric   } else {
5235ffd83dbSDimitry Andric     assert(Output.isFilename() && "Unexpected ld output.");
5245ffd83dbSDimitry Andric     SmallString<128> F;
5255ffd83dbSDimitry Andric     F = Output.getFilename();
5265ffd83dbSDimitry Andric     F += ".opt.";
5275ffd83dbSDimitry Andric     F += Format;
5285ffd83dbSDimitry Andric 
5295ffd83dbSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(F));
5305ffd83dbSDimitry Andric   }
5315ffd83dbSDimitry Andric 
5325ffd83dbSDimitry Andric   if (const Arg *A =
5335ffd83dbSDimitry Andric           Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
5345ffd83dbSDimitry Andric     CmdArgs.push_back("-mllvm");
5355ffd83dbSDimitry Andric     std::string Passes =
5365ffd83dbSDimitry Andric         std::string("-lto-pass-remarks-filter=") + A->getValue();
5375ffd83dbSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Passes));
5385ffd83dbSDimitry Andric   }
5395ffd83dbSDimitry Andric 
5405ffd83dbSDimitry Andric   if (!Format.empty()) {
5415ffd83dbSDimitry Andric     CmdArgs.push_back("-mllvm");
5425ffd83dbSDimitry Andric     Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
5435ffd83dbSDimitry Andric     CmdArgs.push_back(Args.MakeArgString(FormatArg));
5445ffd83dbSDimitry Andric   }
5455ffd83dbSDimitry Andric 
5465ffd83dbSDimitry Andric   if (getLastProfileUseArg(Args)) {
5475ffd83dbSDimitry Andric     CmdArgs.push_back("-mllvm");
5485ffd83dbSDimitry Andric     CmdArgs.push_back("-lto-pass-remarks-with-hotness");
5495ffd83dbSDimitry Andric 
5505ffd83dbSDimitry Andric     if (const Arg *A =
5515ffd83dbSDimitry Andric             Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
5525ffd83dbSDimitry Andric       CmdArgs.push_back("-mllvm");
5535ffd83dbSDimitry Andric       std::string Opt =
5545ffd83dbSDimitry Andric           std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
5555ffd83dbSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Opt));
5565ffd83dbSDimitry Andric     }
5575ffd83dbSDimitry Andric   }
5585ffd83dbSDimitry Andric }
5595ffd83dbSDimitry Andric 
560bdd1243dSDimitry Andric static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);
561bdd1243dSDimitry Andric 
5620b57cec5SDimitry Andric void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
5630b57cec5SDimitry Andric                                   const InputInfo &Output,
5640b57cec5SDimitry Andric                                   const InputInfoList &Inputs,
5650b57cec5SDimitry Andric                                   const ArgList &Args,
5660b57cec5SDimitry Andric                                   const char *LinkingOutput) const {
5670b57cec5SDimitry Andric   assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   // If the number of arguments surpasses the system limits, we will encode the
5700b57cec5SDimitry Andric   // input files in a separate file, shortening the command line. To this end,
5710b57cec5SDimitry Andric   // build a list of input file names that can be passed via a file with the
5720b57cec5SDimitry Andric   // -filelist linker option.
5730b57cec5SDimitry Andric   llvm::opt::ArgStringList InputFileList;
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   // The logic here is derived from gcc's behavior; most of which
5760b57cec5SDimitry Andric   // comes from specs (starting with link_command). Consult gcc for
5770b57cec5SDimitry Andric   // more information.
5780b57cec5SDimitry Andric   ArgStringList CmdArgs;
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   /// Hack(tm) to ignore linking errors when we are doing ARC migration.
5810b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_ccc_arcmt_check,
5820b57cec5SDimitry Andric                   options::OPT_ccc_arcmt_migrate)) {
5830b57cec5SDimitry Andric     for (const auto &Arg : Args)
5840b57cec5SDimitry Andric       Arg->claim();
5850b57cec5SDimitry Andric     const char *Exec =
5860b57cec5SDimitry Andric         Args.MakeArgString(getToolChain().GetProgramPath("touch"));
5870b57cec5SDimitry Andric     CmdArgs.push_back(Output.getFilename());
588bdd1243dSDimitry Andric     C.addCommand(std::make_unique<Command>(JA, *this,
589bdd1243dSDimitry Andric                                            ResponseFileSupport::None(), Exec,
590bdd1243dSDimitry Andric                                            CmdArgs, std::nullopt, Output));
5910b57cec5SDimitry Andric     return;
5920b57cec5SDimitry Andric   }
5930b57cec5SDimitry Andric 
59481ad6265SDimitry Andric   VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
5955ffd83dbSDimitry Andric 
5960eae32dcSDimitry Andric   bool LinkerIsLLD;
5970eae32dcSDimitry Andric   const char *Exec =
5980eae32dcSDimitry Andric       Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));
599e8d8bef9SDimitry Andric 
6007a6dacacSDimitry Andric   // xrOS always uses -platform-version.
6017a6dacacSDimitry Andric   bool UsePlatformVersion = getToolChain().getTriple().isXROS();
6027a6dacacSDimitry Andric 
6030b57cec5SDimitry Andric   // I'm not sure why this particular decomposition exists in gcc, but
6040b57cec5SDimitry Andric   // we follow suite for ease of comparison.
6057a6dacacSDimitry Andric   AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,
6067a6dacacSDimitry Andric               UsePlatformVersion);
6070b57cec5SDimitry Andric 
6085ffd83dbSDimitry Andric   if (willEmitRemarks(Args) &&
6095ffd83dbSDimitry Andric       checkRemarksOptions(getToolChain().getDriver(), Args,
6105ffd83dbSDimitry Andric                           getToolChain().getTriple()))
6115ffd83dbSDimitry Andric     renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   // Propagate the -moutline flag to the linker in LTO.
6140b57cec5SDimitry Andric   if (Arg *A =
6150b57cec5SDimitry Andric           Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {
6160b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_moutline)) {
6170b57cec5SDimitry Andric       if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
6180b57cec5SDimitry Andric         CmdArgs.push_back("-mllvm");
6190b57cec5SDimitry Andric         CmdArgs.push_back("-enable-machine-outliner");
6200b57cec5SDimitry Andric       }
6210b57cec5SDimitry Andric     } else {
6220b57cec5SDimitry Andric       // Disable all outlining behaviour if we have mno-outline. We need to do
6230b57cec5SDimitry Andric       // this explicitly, because targets which support default outlining will
6240b57cec5SDimitry Andric       // try to do work if we don't.
6250b57cec5SDimitry Andric       CmdArgs.push_back("-mllvm");
6260b57cec5SDimitry Andric       CmdArgs.push_back("-enable-machine-outliner=never");
6270b57cec5SDimitry Andric     }
6280b57cec5SDimitry Andric   }
6290b57cec5SDimitry Andric 
6305f757f3fSDimitry Andric   // Outline from linkonceodr functions by default in LTO, whenever the outliner
6315f757f3fSDimitry Andric   // is enabled.  Note that the target may enable the machine outliner
6325f757f3fSDimitry Andric   // independently of -moutline.
6335f757f3fSDimitry Andric   CmdArgs.push_back("-mllvm");
6345f757f3fSDimitry Andric   CmdArgs.push_back("-enable-linkonceodr-outlining");
6355f757f3fSDimitry Andric 
6360b57cec5SDimitry Andric   // Setup statistics file output.
6370b57cec5SDimitry Andric   SmallString<128> StatsFile =
6380b57cec5SDimitry Andric       getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
6390b57cec5SDimitry Andric   if (!StatsFile.empty()) {
6400b57cec5SDimitry Andric     CmdArgs.push_back("-mllvm");
6410b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));
6420b57cec5SDimitry Andric   }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   // It seems that the 'e' option is completely ignored for dynamic executables
6450b57cec5SDimitry Andric   // (the default), and with static executables, the last one wins, as expected.
6460fca6ea1SDimitry Andric   Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
6470fca6ea1SDimitry Andric                             options::OPT_Z_Flag, options::OPT_u_Group});
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
6500b57cec5SDimitry Andric   // members of static archive libraries which implement Objective-C classes or
6510b57cec5SDimitry Andric   // categories.
6520b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
6530b57cec5SDimitry Andric     CmdArgs.push_back("-ObjC");
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   CmdArgs.push_back("-o");
6560b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
6590b57cec5SDimitry Andric     getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_L);
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
6640b57cec5SDimitry Andric   // Build the input file for -filelist (list of linker input files) in case we
6650b57cec5SDimitry Andric   // need it later
6660b57cec5SDimitry Andric   for (const auto &II : Inputs) {
6670b57cec5SDimitry Andric     if (!II.isFilename()) {
6680b57cec5SDimitry Andric       // This is a linker input argument.
6690b57cec5SDimitry Andric       // We cannot mix input arguments and file names in a -filelist input, thus
6700b57cec5SDimitry Andric       // we prematurely stop our list (remaining files shall be passed as
6710b57cec5SDimitry Andric       // arguments).
6720b57cec5SDimitry Andric       if (InputFileList.size() > 0)
6730b57cec5SDimitry Andric         break;
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric       continue;
6760b57cec5SDimitry Andric     }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric     InputFileList.push_back(II.getFilename());
6790b57cec5SDimitry Andric   }
6800b57cec5SDimitry Andric 
68181ad6265SDimitry Andric   // Additional linker set-up and flags for Fortran. This is required in order
68281ad6265SDimitry Andric   // to generate executables.
68381ad6265SDimitry Andric   if (getToolChain().getDriver().IsFlangMode()) {
68481ad6265SDimitry Andric     addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
6855f757f3fSDimitry Andric     addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
68681ad6265SDimitry Andric   }
68781ad6265SDimitry Andric 
6880b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
6890fca6ea1SDimitry Andric     addOpenMPRuntime(C, CmdArgs, getToolChain(), Args);
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   if (isObjCRuntimeLinked(Args) &&
6920b57cec5SDimitry Andric       !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
6930b57cec5SDimitry Andric     // We use arclite library for both ARC and subscripting support.
6940b57cec5SDimitry Andric     getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric     CmdArgs.push_back("-framework");
6970b57cec5SDimitry Andric     CmdArgs.push_back("Foundation");
6980b57cec5SDimitry Andric     // Link libobj.
6990b57cec5SDimitry Andric     CmdArgs.push_back("-lobjc");
7000b57cec5SDimitry Andric   }
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   if (LinkingOutput) {
7030b57cec5SDimitry Andric     CmdArgs.push_back("-arch_multiple");
7040b57cec5SDimitry Andric     CmdArgs.push_back("-final_output");
7050b57cec5SDimitry Andric     CmdArgs.push_back(LinkingOutput);
7060b57cec5SDimitry Andric   }
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_fnested_functions))
7090b57cec5SDimitry Andric     CmdArgs.push_back("-allow_stack_execute");
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
7120b57cec5SDimitry Andric 
7135ffd83dbSDimitry Andric   StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
7145ffd83dbSDimitry Andric   if (!Parallelism.empty()) {
7150b57cec5SDimitry Andric     CmdArgs.push_back("-mllvm");
7165ffd83dbSDimitry Andric     unsigned NumThreads =
7175ffd83dbSDimitry Andric         llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
7185ffd83dbSDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
7190b57cec5SDimitry Andric   }
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric   if (getToolChain().ShouldLinkCXXStdlib(Args))
7220b57cec5SDimitry Andric     getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric   bool NoStdOrDefaultLibs =
7250b57cec5SDimitry Andric       Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
7260b57cec5SDimitry Andric   bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
7270b57cec5SDimitry Andric   if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
7280b57cec5SDimitry Andric     // link_ssp spec is empty.
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric     // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
7310b57cec5SDimitry Andric     // we just want to link the builtins, not the other libs like libSystem.
7320b57cec5SDimitry Andric     if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
7330b57cec5SDimitry Andric       getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");
7340b57cec5SDimitry Andric     } else {
7350b57cec5SDimitry Andric       // Let the tool chain choose which runtime library to link.
7360b57cec5SDimitry Andric       getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
7370b57cec5SDimitry Andric                                                 ForceLinkBuiltins);
7380b57cec5SDimitry Andric 
7390b57cec5SDimitry Andric       // No need to do anything for pthreads. Claim argument to avoid warning.
7400b57cec5SDimitry Andric       Args.ClaimAllArgs(options::OPT_pthread);
7410b57cec5SDimitry Andric       Args.ClaimAllArgs(options::OPT_pthreads);
7420b57cec5SDimitry Andric     }
7430b57cec5SDimitry Andric   }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
7460b57cec5SDimitry Andric     // endfile_spec is empty.
7470b57cec5SDimitry Andric   }
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
7500b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_F);
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric   // -iframework should be forwarded as -F.
7530b57cec5SDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_iframework))
7540b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
7570b57cec5SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
7580b57cec5SDimitry Andric       if (A->getValue() == StringRef("Accelerate")) {
7590b57cec5SDimitry Andric         CmdArgs.push_back("-framework");
7600b57cec5SDimitry Andric         CmdArgs.push_back("Accelerate");
7610b57cec5SDimitry Andric       }
7620b57cec5SDimitry Andric     }
7630b57cec5SDimitry Andric   }
7640b57cec5SDimitry Andric 
765bdd1243dSDimitry Andric   // Add non-standard, platform-specific search paths, e.g., for DriverKit:
766bdd1243dSDimitry Andric   //  -L<sysroot>/System/DriverKit/usr/lib
767bdd1243dSDimitry Andric   //  -F<sysroot>/System/DriverKit/System/Library/Framework
768bdd1243dSDimitry Andric   {
769bdd1243dSDimitry Andric     bool NonStandardSearchPath = false;
770bdd1243dSDimitry Andric     const auto &Triple = getToolChain().getTriple();
771bdd1243dSDimitry Andric     if (Triple.isDriverKit()) {
77281ad6265SDimitry Andric       // ld64 fixed the implicit -F and -L paths in ld64-605.1+.
773bdd1243dSDimitry Andric       NonStandardSearchPath =
774bdd1243dSDimitry Andric           Version.getMajor() < 605 ||
775bdd1243dSDimitry Andric           (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);
776bdd1243dSDimitry Andric     }
77781ad6265SDimitry Andric 
778bdd1243dSDimitry Andric     if (NonStandardSearchPath) {
779bdd1243dSDimitry Andric       if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
780bdd1243dSDimitry Andric         auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
781bdd1243dSDimitry Andric           SmallString<128> P(Sysroot->getValue());
782bdd1243dSDimitry Andric           AppendPlatformPrefix(P, Triple);
783bdd1243dSDimitry Andric           llvm::sys::path::append(P, SearchPath);
784bdd1243dSDimitry Andric           if (getToolChain().getVFS().exists(P)) {
785bdd1243dSDimitry Andric             CmdArgs.push_back(Args.MakeArgString(Flag + P));
786bdd1243dSDimitry Andric           }
787bdd1243dSDimitry Andric         };
788bdd1243dSDimitry Andric         AddSearchPath("-L", "/usr/lib");
789bdd1243dSDimitry Andric         AddSearchPath("-F", "/System/Library/Frameworks");
79081ad6265SDimitry Andric       }
79181ad6265SDimitry Andric     }
79281ad6265SDimitry Andric   }
79381ad6265SDimitry Andric 
794e8d8bef9SDimitry Andric   ResponseFileSupport ResponseSupport;
79581ad6265SDimitry Andric   if (Version >= VersionTuple(705) || LinkerIsLLD) {
796e8d8bef9SDimitry Andric     ResponseSupport = ResponseFileSupport::AtFileUTF8();
797e8d8bef9SDimitry Andric   } else {
7985ffd83dbSDimitry Andric     // For older versions of the linker, use the legacy filelist method instead.
7995ffd83dbSDimitry Andric     ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
8005ffd83dbSDimitry Andric                        "-filelist"};
8015ffd83dbSDimitry Andric   }
8025ffd83dbSDimitry Andric 
8035ffd83dbSDimitry Andric   std::unique_ptr<Command> Cmd = std::make_unique<Command>(
804e8d8bef9SDimitry Andric       JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
8050b57cec5SDimitry Andric   Cmd->setInputFileList(std::move(InputFileList));
8060b57cec5SDimitry Andric   C.addCommand(std::move(Cmd));
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric 
809349cc55cSDimitry Andric void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
810349cc55cSDimitry Andric                                          const InputInfo &Output,
811349cc55cSDimitry Andric                                          const InputInfoList &Inputs,
812349cc55cSDimitry Andric                                          const ArgList &Args,
813349cc55cSDimitry Andric                                          const char *LinkingOutput) const {
814349cc55cSDimitry Andric   const Driver &D = getToolChain().getDriver();
815349cc55cSDimitry Andric 
816349cc55cSDimitry Andric   // Silence warning for "clang -g foo.o -o foo"
817349cc55cSDimitry Andric   Args.ClaimAllArgs(options::OPT_g_Group);
818349cc55cSDimitry Andric   // and "clang -emit-llvm foo.o -o foo"
819349cc55cSDimitry Andric   Args.ClaimAllArgs(options::OPT_emit_llvm);
820349cc55cSDimitry Andric   // and for "clang -w foo.o -o foo". Other warning options are already
821349cc55cSDimitry Andric   // handled somewhere else.
822349cc55cSDimitry Andric   Args.ClaimAllArgs(options::OPT_w);
823349cc55cSDimitry Andric   // Silence warnings when linking C code with a C++ '-stdlib' argument.
824349cc55cSDimitry Andric   Args.ClaimAllArgs(options::OPT_stdlib_EQ);
825349cc55cSDimitry Andric 
826349cc55cSDimitry Andric   // libtool <options> <output_file> <input_files>
827349cc55cSDimitry Andric   ArgStringList CmdArgs;
828349cc55cSDimitry Andric   // Create and insert file members with a deterministic index.
829349cc55cSDimitry Andric   CmdArgs.push_back("-static");
830349cc55cSDimitry Andric   CmdArgs.push_back("-D");
831349cc55cSDimitry Andric   CmdArgs.push_back("-no_warning_for_no_symbols");
832349cc55cSDimitry Andric   CmdArgs.push_back("-o");
833349cc55cSDimitry Andric   CmdArgs.push_back(Output.getFilename());
834349cc55cSDimitry Andric 
835349cc55cSDimitry Andric   for (const auto &II : Inputs) {
836349cc55cSDimitry Andric     if (II.isFilename()) {
837349cc55cSDimitry Andric       CmdArgs.push_back(II.getFilename());
838349cc55cSDimitry Andric     }
839349cc55cSDimitry Andric   }
840349cc55cSDimitry Andric 
841349cc55cSDimitry Andric   // Delete old output archive file if it already exists before generating a new
842349cc55cSDimitry Andric   // archive file.
843349cc55cSDimitry Andric   const auto *OutputFileName = Output.getFilename();
844349cc55cSDimitry Andric   if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
845349cc55cSDimitry Andric     if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
846349cc55cSDimitry Andric       D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
847349cc55cSDimitry Andric       return;
848349cc55cSDimitry Andric     }
849349cc55cSDimitry Andric   }
850349cc55cSDimitry Andric 
851349cc55cSDimitry Andric   const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
852349cc55cSDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
853349cc55cSDimitry Andric                                          ResponseFileSupport::AtFileUTF8(),
854349cc55cSDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
855349cc55cSDimitry Andric }
856349cc55cSDimitry Andric 
8570b57cec5SDimitry Andric void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
8580b57cec5SDimitry Andric                                 const InputInfo &Output,
8590b57cec5SDimitry Andric                                 const InputInfoList &Inputs,
8600b57cec5SDimitry Andric                                 const ArgList &Args,
8610b57cec5SDimitry Andric                                 const char *LinkingOutput) const {
8620b57cec5SDimitry Andric   ArgStringList CmdArgs;
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   CmdArgs.push_back("-create");
8650b57cec5SDimitry Andric   assert(Output.isFilename() && "Unexpected lipo output.");
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric   CmdArgs.push_back("-output");
8680b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   for (const auto &II : Inputs) {
8710b57cec5SDimitry Andric     assert(II.isFilename() && "Unexpected lipo input.");
8720b57cec5SDimitry Andric     CmdArgs.push_back(II.getFilename());
8730b57cec5SDimitry Andric   }
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
8765ffd83dbSDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
877e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
8810b57cec5SDimitry Andric                                     const InputInfo &Output,
8820b57cec5SDimitry Andric                                     const InputInfoList &Inputs,
8830b57cec5SDimitry Andric                                     const ArgList &Args,
8840b57cec5SDimitry Andric                                     const char *LinkingOutput) const {
8850b57cec5SDimitry Andric   ArgStringList CmdArgs;
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   CmdArgs.push_back("-o");
8880b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
8910b57cec5SDimitry Andric   const InputInfo &Input = Inputs[0];
8920b57cec5SDimitry Andric   assert(Input.isFilename() && "Unexpected dsymutil input.");
8930b57cec5SDimitry Andric   CmdArgs.push_back(Input.getFilename());
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   const char *Exec =
8960b57cec5SDimitry Andric       Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
8975ffd83dbSDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
898e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
8990b57cec5SDimitry Andric }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
9020b57cec5SDimitry Andric                                        const InputInfo &Output,
9030b57cec5SDimitry Andric                                        const InputInfoList &Inputs,
9040b57cec5SDimitry Andric                                        const ArgList &Args,
9050b57cec5SDimitry Andric                                        const char *LinkingOutput) const {
9060b57cec5SDimitry Andric   ArgStringList CmdArgs;
9070b57cec5SDimitry Andric   CmdArgs.push_back("--verify");
9080b57cec5SDimitry Andric   CmdArgs.push_back("--debug-info");
9090b57cec5SDimitry Andric   CmdArgs.push_back("--eh-frame");
9100b57cec5SDimitry Andric   CmdArgs.push_back("--quiet");
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
9130b57cec5SDimitry Andric   const InputInfo &Input = Inputs[0];
9140b57cec5SDimitry Andric   assert(Input.isFilename() && "Unexpected verify input");
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric   // Grabbing the output of the earlier dsymutil run.
9170b57cec5SDimitry Andric   CmdArgs.push_back(Input.getFilename());
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   const char *Exec =
9200b57cec5SDimitry Andric       Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
9215ffd83dbSDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
922e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
9230b57cec5SDimitry Andric }
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
9260b57cec5SDimitry Andric     : ToolChain(D, Triple, Args) {
9270b57cec5SDimitry Andric   // We expect 'as', 'ld', etc. to be adjacent to our install dir.
9280b57cec5SDimitry Andric   getProgramPaths().push_back(getDriver().Dir);
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric /// Darwin - Darwin tool chain for i386 and x86_64.
9320b57cec5SDimitry Andric Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
9330b57cec5SDimitry Andric     : MachO(D, Triple, Args), TargetInitialized(false),
9345ffd83dbSDimitry Andric       CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
937480093f4SDimitry Andric   types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   // Darwin always preprocesses assembly files (unless -x is used explicitly).
9400b57cec5SDimitry Andric   if (Ty == types::TY_PP_Asm)
9410b57cec5SDimitry Andric     return types::TY_Asm;
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric   return Ty;
9440b57cec5SDimitry Andric }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric bool MachO::HasNativeLLVMSupport() const { return true; }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
949bdd1243dSDimitry Andric   // Always use libc++ by default
95081ad6265SDimitry Andric   return ToolChain::CST_Libcxx;
9510b57cec5SDimitry Andric }
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
9540b57cec5SDimitry Andric ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
9550b57cec5SDimitry Andric   if (isTargetWatchOSBased())
9560b57cec5SDimitry Andric     return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
9570b57cec5SDimitry Andric   if (isTargetIOSBased())
9580b57cec5SDimitry Andric     return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
9597a6dacacSDimitry Andric   if (isTargetXROS()) {
9607a6dacacSDimitry Andric     // XROS uses the iOS runtime.
9617a6dacacSDimitry Andric     auto T = llvm::Triple(Twine("arm64-apple-") +
9627a6dacacSDimitry Andric                           llvm::Triple::getOSTypeName(llvm::Triple::XROS) +
9637a6dacacSDimitry Andric                           TargetVersion.getAsString());
9647a6dacacSDimitry Andric     return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion());
9657a6dacacSDimitry Andric   }
9660b57cec5SDimitry Andric   if (isNonFragile)
9670b57cec5SDimitry Andric     return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
9680b57cec5SDimitry Andric   return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
9690b57cec5SDimitry Andric }
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
9720b57cec5SDimitry Andric bool Darwin::hasBlocksRuntime() const {
9737a6dacacSDimitry Andric   if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())
9740b57cec5SDimitry Andric     return true;
9750b57cec5SDimitry Andric   else if (isTargetIOSBased())
9760b57cec5SDimitry Andric     return !isIPhoneOSVersionLT(3, 2);
9770b57cec5SDimitry Andric   else {
978fe6060f1SDimitry Andric     assert(isTargetMacOSBased() && "unexpected darwin target");
9790b57cec5SDimitry Andric     return !isMacosxVersionLT(10, 6);
9800b57cec5SDimitry Andric   }
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
9840b57cec5SDimitry Andric                                 ArgStringList &CC1Args) const {
9857a6dacacSDimitry Andric   CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
9885ffd83dbSDimitry Andric void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
9895ffd83dbSDimitry Andric                                ArgStringList &CC1Args) const {
9907a6dacacSDimitry Andric   RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
9915ffd83dbSDimitry Andric }
9925ffd83dbSDimitry Andric 
9930b57cec5SDimitry Andric // This is just a MachO name translation routine and there's no
9940b57cec5SDimitry Andric // way to join this into ARMTargetParser without breaking all
9950b57cec5SDimitry Andric // other assumptions. Maybe MachO should consider standardising
9960b57cec5SDimitry Andric // their nomenclature.
9970b57cec5SDimitry Andric static const char *ArmMachOArchName(StringRef Arch) {
9980b57cec5SDimitry Andric   return llvm::StringSwitch<const char *>(Arch)
9990b57cec5SDimitry Andric       .Case("armv6k", "armv6")
10000b57cec5SDimitry Andric       .Case("armv6m", "armv6m")
10010b57cec5SDimitry Andric       .Case("armv5tej", "armv5")
10020b57cec5SDimitry Andric       .Case("xscale", "xscale")
10030b57cec5SDimitry Andric       .Case("armv4t", "armv4t")
10040b57cec5SDimitry Andric       .Case("armv7", "armv7")
10050b57cec5SDimitry Andric       .Cases("armv7a", "armv7-a", "armv7")
10060b57cec5SDimitry Andric       .Cases("armv7r", "armv7-r", "armv7")
10070b57cec5SDimitry Andric       .Cases("armv7em", "armv7e-m", "armv7em")
10080b57cec5SDimitry Andric       .Cases("armv7k", "armv7-k", "armv7k")
10090b57cec5SDimitry Andric       .Cases("armv7m", "armv7-m", "armv7m")
10100b57cec5SDimitry Andric       .Cases("armv7s", "armv7-s", "armv7s")
10110b57cec5SDimitry Andric       .Default(nullptr);
10120b57cec5SDimitry Andric }
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric static const char *ArmMachOArchNameCPU(StringRef CPU) {
10150b57cec5SDimitry Andric   llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
10160b57cec5SDimitry Andric   if (ArchKind == llvm::ARM::ArchKind::INVALID)
10170b57cec5SDimitry Andric     return nullptr;
10180b57cec5SDimitry Andric   StringRef Arch = llvm::ARM::getArchName(ArchKind);
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   // FIXME: Make sure this MachO triple mangling is really necessary.
10210b57cec5SDimitry Andric   // ARMv5* normalises to ARMv5.
10225f757f3fSDimitry Andric   if (Arch.starts_with("armv5"))
10230b57cec5SDimitry Andric     Arch = Arch.substr(0, 5);
10240b57cec5SDimitry Andric   // ARMv6*, except ARMv6M, normalises to ARMv6.
10255f757f3fSDimitry Andric   else if (Arch.starts_with("armv6") && !Arch.ends_with("6m"))
10260b57cec5SDimitry Andric     Arch = Arch.substr(0, 5);
10270b57cec5SDimitry Andric   // ARMv7A normalises to ARMv7.
10285f757f3fSDimitry Andric   else if (Arch.ends_with("v7a"))
10290b57cec5SDimitry Andric     Arch = Arch.substr(0, 5);
10300b57cec5SDimitry Andric   return Arch.data();
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
10330b57cec5SDimitry Andric StringRef MachO::getMachOArchName(const ArgList &Args) const {
10340b57cec5SDimitry Andric   switch (getTriple().getArch()) {
10350b57cec5SDimitry Andric   default:
10360b57cec5SDimitry Andric     return getDefaultUniversalArchName();
10370b57cec5SDimitry Andric 
1038480093f4SDimitry Andric   case llvm::Triple::aarch64_32:
1039480093f4SDimitry Andric     return "arm64_32";
1040480093f4SDimitry Andric 
1041e8d8bef9SDimitry Andric   case llvm::Triple::aarch64: {
1042e8d8bef9SDimitry Andric     if (getTriple().isArm64e())
1043e8d8bef9SDimitry Andric       return "arm64e";
10440b57cec5SDimitry Andric     return "arm64";
1045e8d8bef9SDimitry Andric   }
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   case llvm::Triple::thumb:
10480b57cec5SDimitry Andric   case llvm::Triple::arm:
10490b57cec5SDimitry Andric     if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
10500b57cec5SDimitry Andric       if (const char *Arch = ArmMachOArchName(A->getValue()))
10510b57cec5SDimitry Andric         return Arch;
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
10540b57cec5SDimitry Andric       if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
10550b57cec5SDimitry Andric         return Arch;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric     return "arm";
10580b57cec5SDimitry Andric   }
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
106181ad6265SDimitry Andric VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
106281ad6265SDimitry Andric   if (LinkerVersion) {
106381ad6265SDimitry Andric #ifndef NDEBUG
106481ad6265SDimitry Andric     VersionTuple NewLinkerVersion;
106581ad6265SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
106681ad6265SDimitry Andric       (void)NewLinkerVersion.tryParse(A->getValue());
106781ad6265SDimitry Andric     assert(NewLinkerVersion == LinkerVersion);
106881ad6265SDimitry Andric #endif
106981ad6265SDimitry Andric     return *LinkerVersion;
107081ad6265SDimitry Andric   }
107181ad6265SDimitry Andric 
107281ad6265SDimitry Andric   VersionTuple NewLinkerVersion;
107381ad6265SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
107481ad6265SDimitry Andric     if (NewLinkerVersion.tryParse(A->getValue()))
107581ad6265SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
107681ad6265SDimitry Andric         << A->getAsString(Args);
107781ad6265SDimitry Andric 
107881ad6265SDimitry Andric   LinkerVersion = NewLinkerVersion;
107981ad6265SDimitry Andric   return *LinkerVersion;
108081ad6265SDimitry Andric }
108181ad6265SDimitry Andric 
10820b57cec5SDimitry Andric Darwin::~Darwin() {}
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric MachO::~MachO() {}
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
10870b57cec5SDimitry Andric                                                 types::ID InputType) const {
10880b57cec5SDimitry Andric   llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric   // If the target isn't initialized (e.g., an unknown Darwin platform, return
10910b57cec5SDimitry Andric   // the default triple).
10920b57cec5SDimitry Andric   if (!isTargetInitialized())
10930b57cec5SDimitry Andric     return Triple.getTriple();
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric   SmallString<16> Str;
10960b57cec5SDimitry Andric   if (isTargetWatchOSBased())
10970b57cec5SDimitry Andric     Str += "watchos";
10980b57cec5SDimitry Andric   else if (isTargetTvOSBased())
10990b57cec5SDimitry Andric     Str += "tvos";
110081ad6265SDimitry Andric   else if (isTargetDriverKit())
110181ad6265SDimitry Andric     Str += "driverkit";
1102fe6060f1SDimitry Andric   else if (isTargetIOSBased() || isTargetMacCatalyst())
11030b57cec5SDimitry Andric     Str += "ios";
11047a6dacacSDimitry Andric   else if (isTargetXROS())
11057a6dacacSDimitry Andric     Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS);
11060b57cec5SDimitry Andric   else
11070b57cec5SDimitry Andric     Str += "macosx";
1108fe6060f1SDimitry Andric   Str += getTripleTargetVersion().getAsString();
11090b57cec5SDimitry Andric   Triple.setOSName(Str);
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric   return Triple.getTriple();
11120b57cec5SDimitry Andric }
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric Tool *MachO::getTool(Action::ActionClass AC) const {
11150b57cec5SDimitry Andric   switch (AC) {
11160b57cec5SDimitry Andric   case Action::LipoJobClass:
11170b57cec5SDimitry Andric     if (!Lipo)
11180b57cec5SDimitry Andric       Lipo.reset(new tools::darwin::Lipo(*this));
11190b57cec5SDimitry Andric     return Lipo.get();
11200b57cec5SDimitry Andric   case Action::DsymutilJobClass:
11210b57cec5SDimitry Andric     if (!Dsymutil)
11220b57cec5SDimitry Andric       Dsymutil.reset(new tools::darwin::Dsymutil(*this));
11230b57cec5SDimitry Andric     return Dsymutil.get();
11240b57cec5SDimitry Andric   case Action::VerifyDebugInfoJobClass:
11250b57cec5SDimitry Andric     if (!VerifyDebug)
11260b57cec5SDimitry Andric       VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
11270b57cec5SDimitry Andric     return VerifyDebug.get();
11280b57cec5SDimitry Andric   default:
11290b57cec5SDimitry Andric     return ToolChain::getTool(AC);
11300b57cec5SDimitry Andric   }
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
11340b57cec5SDimitry Andric 
1135349cc55cSDimitry Andric Tool *MachO::buildStaticLibTool() const {
1136349cc55cSDimitry Andric   return new tools::darwin::StaticLibTool(*this);
1137349cc55cSDimitry Andric }
1138349cc55cSDimitry Andric 
11390b57cec5SDimitry Andric Tool *MachO::buildAssembler() const {
11400b57cec5SDimitry Andric   return new tools::darwin::Assembler(*this);
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
11440b57cec5SDimitry Andric                          const ArgList &Args)
11450b57cec5SDimitry Andric     : Darwin(D, Triple, Args) {}
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
11485ffd83dbSDimitry Andric   // Always error about undefined 'TARGET_OS_*' macros.
11495ffd83dbSDimitry Andric   CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
11505ffd83dbSDimitry Andric   CC1Args.push_back("-Werror=undef-prefix");
11515ffd83dbSDimitry Andric 
11520b57cec5SDimitry Andric   // For modern targets, promote certain warnings to errors.
11530b57cec5SDimitry Andric   if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
11540b57cec5SDimitry Andric     // Always enable -Wdeprecated-objc-isa-usage and promote it
11550b57cec5SDimitry Andric     // to an error.
11560b57cec5SDimitry Andric     CC1Args.push_back("-Wdeprecated-objc-isa-usage");
11570b57cec5SDimitry Andric     CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric     // For iOS and watchOS, also error about implicit function declarations,
11600b57cec5SDimitry Andric     // as that can impact calling conventions.
11610b57cec5SDimitry Andric     if (!isTargetMacOS())
11620b57cec5SDimitry Andric       CC1Args.push_back("-Werror=implicit-function-declaration");
11630b57cec5SDimitry Andric   }
11640b57cec5SDimitry Andric }
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric /// Take a path that speculatively points into Xcode and return the
11670b57cec5SDimitry Andric /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path
11680b57cec5SDimitry Andric /// otherwise.
11690b57cec5SDimitry Andric static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
11700b57cec5SDimitry Andric   static constexpr llvm::StringLiteral XcodeAppSuffix(
11710b57cec5SDimitry Andric       ".app/Contents/Developer");
11720b57cec5SDimitry Andric   size_t Index = PathIntoXcode.find(XcodeAppSuffix);
11730b57cec5SDimitry Andric   if (Index == StringRef::npos)
11740b57cec5SDimitry Andric     return "";
11750b57cec5SDimitry Andric   return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());
11760b57cec5SDimitry Andric }
11770b57cec5SDimitry Andric 
11780b57cec5SDimitry Andric void DarwinClang::AddLinkARCArgs(const ArgList &Args,
11790b57cec5SDimitry Andric                                  ArgStringList &CmdArgs) const {
11800b57cec5SDimitry Andric   // Avoid linking compatibility stubs on i386 mac.
1181fe6060f1SDimitry Andric   if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)
11820b57cec5SDimitry Andric     return;
11835ffd83dbSDimitry Andric   if (isTargetAppleSiliconMac())
11845ffd83dbSDimitry Andric     return;
1185e8d8bef9SDimitry Andric   // ARC runtime is supported everywhere on arm64e.
1186e8d8bef9SDimitry Andric   if (getTriple().isArm64e())
1187e8d8bef9SDimitry Andric     return;
11887a6dacacSDimitry Andric   if (isTargetXROS())
11897a6dacacSDimitry Andric     return;
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric   ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric   if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
11940b57cec5SDimitry Andric       runtime.hasSubscripting())
11950b57cec5SDimitry Andric     return;
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   SmallString<128> P(getDriver().ClangExecutable);
11980b57cec5SDimitry Andric   llvm::sys::path::remove_filename(P); // 'clang'
11990b57cec5SDimitry Andric   llvm::sys::path::remove_filename(P); // 'bin'
1200fcaf7f86SDimitry Andric   llvm::sys::path::append(P, "lib", "arc");
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   // 'libarclite' usually lives in the same toolchain as 'clang'. However, the
12030b57cec5SDimitry Andric   // Swift open source toolchains for macOS distribute Clang without libarclite.
12040b57cec5SDimitry Andric   // In that case, to allow the linker to find 'libarclite', we point to the
12050b57cec5SDimitry Andric   // 'libarclite' in the XcodeDefault toolchain instead.
1206fcaf7f86SDimitry Andric   if (!getVFS().exists(P)) {
1207fcaf7f86SDimitry Andric     auto updatePath = [&](const Arg *A) {
12080b57cec5SDimitry Andric       // Try to infer the path to 'libarclite' in the toolchain from the
12090b57cec5SDimitry Andric       // specified SDK path.
12100b57cec5SDimitry Andric       StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
1211fcaf7f86SDimitry Andric       if (XcodePathForSDK.empty())
1212fcaf7f86SDimitry Andric         return false;
1213fcaf7f86SDimitry Andric 
12140b57cec5SDimitry Andric       P = XcodePathForSDK;
1215fcaf7f86SDimitry Andric       llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
1216fcaf7f86SDimitry Andric                               "lib", "arc");
1217fcaf7f86SDimitry Andric       return getVFS().exists(P);
1218fcaf7f86SDimitry Andric     };
1219fcaf7f86SDimitry Andric 
1220fcaf7f86SDimitry Andric     bool updated = false;
1221fcaf7f86SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
1222fcaf7f86SDimitry Andric       updated = updatePath(A);
1223fcaf7f86SDimitry Andric 
1224fcaf7f86SDimitry Andric     if (!updated) {
1225fcaf7f86SDimitry Andric       if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
1226fcaf7f86SDimitry Andric         updatePath(A);
12270b57cec5SDimitry Andric     }
12280b57cec5SDimitry Andric   }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric   CmdArgs.push_back("-force_load");
1231fcaf7f86SDimitry Andric   llvm::sys::path::append(P, "libarclite_");
12320b57cec5SDimitry Andric   // Mash in the platform.
12330b57cec5SDimitry Andric   if (isTargetWatchOSSimulator())
12340b57cec5SDimitry Andric     P += "watchsimulator";
12350b57cec5SDimitry Andric   else if (isTargetWatchOS())
12360b57cec5SDimitry Andric     P += "watchos";
12370b57cec5SDimitry Andric   else if (isTargetTvOSSimulator())
12380b57cec5SDimitry Andric     P += "appletvsimulator";
12390b57cec5SDimitry Andric   else if (isTargetTvOS())
12400b57cec5SDimitry Andric     P += "appletvos";
12410b57cec5SDimitry Andric   else if (isTargetIOSSimulator())
12420b57cec5SDimitry Andric     P += "iphonesimulator";
12430b57cec5SDimitry Andric   else if (isTargetIPhoneOS())
12440b57cec5SDimitry Andric     P += "iphoneos";
12450b57cec5SDimitry Andric   else
12460b57cec5SDimitry Andric     P += "macosx";
12470b57cec5SDimitry Andric   P += ".a";
12480b57cec5SDimitry Andric 
124906c3fb27SDimitry Andric   if (!getVFS().exists(P))
125006c3fb27SDimitry Andric     getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;
125106c3fb27SDimitry Andric 
12520b57cec5SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(P));
12530b57cec5SDimitry Andric }
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric unsigned DarwinClang::GetDefaultDwarfVersion() const {
12560b57cec5SDimitry Andric   // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
1257fe6060f1SDimitry Andric   if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
12580b57cec5SDimitry Andric       (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
12590b57cec5SDimitry Andric     return 2;
12600fca6ea1SDimitry Andric   // Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.
12610fca6ea1SDimitry Andric   if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||
12620fca6ea1SDimitry Andric       (isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||
12630fca6ea1SDimitry Andric       (isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||
12640fca6ea1SDimitry Andric       (isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||
12650fca6ea1SDimitry Andric       (isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||
12660fca6ea1SDimitry Andric       (isTargetMacOSBased() &&
12670fca6ea1SDimitry Andric        TargetVersion.empty())) // apple-darwin, no version.
12680b57cec5SDimitry Andric     return 4;
12690fca6ea1SDimitry Andric   return 5;
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
12730b57cec5SDimitry Andric                               StringRef Component, RuntimeLinkOptions Opts,
12740b57cec5SDimitry Andric                               bool IsShared) const {
12750fca6ea1SDimitry Andric   std::string P = getCompilerRT(
12760fca6ea1SDimitry Andric       Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static);
12770b57cec5SDimitry Andric 
12780b57cec5SDimitry Andric   // For now, allow missing resource libraries to support developers who may
12790b57cec5SDimitry Andric   // not have compiler-rt checked out or integrated into their build (unless
12800b57cec5SDimitry Andric   // we explicitly force linking with this library).
12810b57cec5SDimitry Andric   if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
12820b57cec5SDimitry Andric     const char *LibArg = Args.MakeArgString(P);
12830b57cec5SDimitry Andric     CmdArgs.push_back(LibArg);
12840b57cec5SDimitry Andric   }
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   // Adding the rpaths might negatively interact when other rpaths are involved,
12870b57cec5SDimitry Andric   // so we should make sure we add the rpaths last, after all user-specified
12880b57cec5SDimitry Andric   // rpaths. This is currently true from this place, but we need to be
12890b57cec5SDimitry Andric   // careful if this function is ever called before user's rpaths are emitted.
12900b57cec5SDimitry Andric   if (Opts & RLO_AddRPath) {
12910fca6ea1SDimitry Andric     assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library");
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric     // Add @executable_path to rpath to support having the dylib copied with
12940b57cec5SDimitry Andric     // the executable.
12950b57cec5SDimitry Andric     CmdArgs.push_back("-rpath");
12960b57cec5SDimitry Andric     CmdArgs.push_back("@executable_path");
12970b57cec5SDimitry Andric 
12980fca6ea1SDimitry Andric     // Add the compiler-rt library's directory to rpath to support using the
12990fca6ea1SDimitry Andric     // dylib from the default location without copying.
13000b57cec5SDimitry Andric     CmdArgs.push_back("-rpath");
13010fca6ea1SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P)));
13020b57cec5SDimitry Andric   }
13030b57cec5SDimitry Andric }
13040b57cec5SDimitry Andric 
13050fca6ea1SDimitry Andric std::string MachO::getCompilerRT(const ArgList &, StringRef Component,
13060fca6ea1SDimitry Andric                                  FileType Type) const {
13070fca6ea1SDimitry Andric   assert(Type != ToolChain::FT_Object &&
13080fca6ea1SDimitry Andric          "it doesn't make sense to ask for the compiler-rt library name as an "
13090fca6ea1SDimitry Andric          "object file");
13100fca6ea1SDimitry Andric   SmallString<64> MachOLibName = StringRef("libclang_rt");
13110fca6ea1SDimitry Andric   // On MachO, the builtins component is not in the library name
13120fca6ea1SDimitry Andric   if (Component != "builtins") {
13130fca6ea1SDimitry Andric     MachOLibName += '.';
13140fca6ea1SDimitry Andric     MachOLibName += Component;
13150fca6ea1SDimitry Andric   }
13160fca6ea1SDimitry Andric   MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";
13170fca6ea1SDimitry Andric 
13180fca6ea1SDimitry Andric   SmallString<128> FullPath(getDriver().ResourceDir);
13190fca6ea1SDimitry Andric   llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded",
13200fca6ea1SDimitry Andric                           MachOLibName);
13210fca6ea1SDimitry Andric   return std::string(FullPath);
13220fca6ea1SDimitry Andric }
13230fca6ea1SDimitry Andric 
13240fca6ea1SDimitry Andric std::string Darwin::getCompilerRT(const ArgList &, StringRef Component,
13250fca6ea1SDimitry Andric                                   FileType Type) const {
13260fca6ea1SDimitry Andric   assert(Type != ToolChain::FT_Object &&
13270fca6ea1SDimitry Andric          "it doesn't make sense to ask for the compiler-rt library name as an "
13280fca6ea1SDimitry Andric          "object file");
13290fca6ea1SDimitry Andric   SmallString<64> DarwinLibName = StringRef("libclang_rt.");
13300fca6ea1SDimitry Andric   // On Darwin, the builtins component is not in the library name
13310fca6ea1SDimitry Andric   if (Component != "builtins") {
13320fca6ea1SDimitry Andric     DarwinLibName += Component;
13330fca6ea1SDimitry Andric     DarwinLibName += '_';
13340fca6ea1SDimitry Andric   }
13350fca6ea1SDimitry Andric   DarwinLibName += getOSLibraryNameSuffix();
13360fca6ea1SDimitry Andric   DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";
13370fca6ea1SDimitry Andric 
13380fca6ea1SDimitry Andric   SmallString<128> FullPath(getDriver().ResourceDir);
13390fca6ea1SDimitry Andric   llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName);
13400fca6ea1SDimitry Andric   return std::string(FullPath);
13410fca6ea1SDimitry Andric }
13420fca6ea1SDimitry Andric 
13430b57cec5SDimitry Andric StringRef Darwin::getPlatformFamily() const {
13440b57cec5SDimitry Andric   switch (TargetPlatform) {
13450b57cec5SDimitry Andric     case DarwinPlatformKind::MacOS:
13460b57cec5SDimitry Andric       return "MacOSX";
13470b57cec5SDimitry Andric     case DarwinPlatformKind::IPhoneOS:
1348fe6060f1SDimitry Andric       if (TargetEnvironment == MacCatalyst)
1349fe6060f1SDimitry Andric         return "MacOSX";
13500b57cec5SDimitry Andric       return "iPhone";
13510b57cec5SDimitry Andric     case DarwinPlatformKind::TvOS:
13520b57cec5SDimitry Andric       return "AppleTV";
13530b57cec5SDimitry Andric     case DarwinPlatformKind::WatchOS:
13540b57cec5SDimitry Andric       return "Watch";
135581ad6265SDimitry Andric     case DarwinPlatformKind::DriverKit:
135681ad6265SDimitry Andric       return "DriverKit";
13577a6dacacSDimitry Andric     case DarwinPlatformKind::XROS:
13587a6dacacSDimitry Andric       return "XR";
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric   llvm_unreachable("Unsupported platform");
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric StringRef Darwin::getSDKName(StringRef isysroot) {
13640b57cec5SDimitry Andric   // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
13655ffd83dbSDimitry Andric   auto BeginSDK = llvm::sys::path::rbegin(isysroot);
13665ffd83dbSDimitry Andric   auto EndSDK = llvm::sys::path::rend(isysroot);
13670b57cec5SDimitry Andric   for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
13680b57cec5SDimitry Andric     StringRef SDK = *IT;
13695f757f3fSDimitry Andric     if (SDK.ends_with(".sdk"))
13700b57cec5SDimitry Andric         return SDK.slice(0, SDK.size() - 4);
13710b57cec5SDimitry Andric   }
13720b57cec5SDimitry Andric   return "";
13730b57cec5SDimitry Andric }
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
13760b57cec5SDimitry Andric   switch (TargetPlatform) {
13770b57cec5SDimitry Andric   case DarwinPlatformKind::MacOS:
13780b57cec5SDimitry Andric     return "osx";
13790b57cec5SDimitry Andric   case DarwinPlatformKind::IPhoneOS:
1380fe6060f1SDimitry Andric     if (TargetEnvironment == MacCatalyst)
1381fe6060f1SDimitry Andric       return "osx";
13820b57cec5SDimitry Andric     return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
13830b57cec5SDimitry Andric                                                                : "iossim";
13840b57cec5SDimitry Andric   case DarwinPlatformKind::TvOS:
13850b57cec5SDimitry Andric     return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
13860b57cec5SDimitry Andric                                                                : "tvossim";
13870b57cec5SDimitry Andric   case DarwinPlatformKind::WatchOS:
13880b57cec5SDimitry Andric     return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
13890b57cec5SDimitry Andric                                                                : "watchossim";
13907a6dacacSDimitry Andric   case DarwinPlatformKind::XROS:
13917a6dacacSDimitry Andric     return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros"
13927a6dacacSDimitry Andric                                                                : "xrossim";
139381ad6265SDimitry Andric   case DarwinPlatformKind::DriverKit:
139481ad6265SDimitry Andric     return "driverkit";
13950b57cec5SDimitry Andric   }
13960b57cec5SDimitry Andric   llvm_unreachable("Unsupported platform");
13970b57cec5SDimitry Andric }
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric /// Check if the link command contains a symbol export directive.
14000b57cec5SDimitry Andric static bool hasExportSymbolDirective(const ArgList &Args) {
14010b57cec5SDimitry Andric   for (Arg *A : Args) {
14020b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_exported__symbols__list))
14030b57cec5SDimitry Andric       return true;
14040b57cec5SDimitry Andric     if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
14050b57cec5SDimitry Andric         !A->getOption().matches(options::OPT_Xlinker))
14060b57cec5SDimitry Andric       continue;
14070b57cec5SDimitry Andric     if (A->containsValue("-exported_symbols_list") ||
14080b57cec5SDimitry Andric         A->containsValue("-exported_symbol"))
14090b57cec5SDimitry Andric       return true;
14100b57cec5SDimitry Andric   }
14110b57cec5SDimitry Andric   return false;
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric /// Add an export directive for \p Symbol to the link command.
14150b57cec5SDimitry Andric static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
14160b57cec5SDimitry Andric   CmdArgs.push_back("-exported_symbol");
14170b57cec5SDimitry Andric   CmdArgs.push_back(Symbol);
14180b57cec5SDimitry Andric }
14190b57cec5SDimitry Andric 
1420480093f4SDimitry Andric /// Add a sectalign directive for \p Segment and \p Section to the maximum
1421480093f4SDimitry Andric /// expected page size for Darwin.
1422480093f4SDimitry Andric ///
1423480093f4SDimitry Andric /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
1424480093f4SDimitry Andric /// Use a common alignment constant (16K) for now, and reduce the alignment on
1425480093f4SDimitry Andric /// macOS if it proves important.
1426480093f4SDimitry Andric static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
1427480093f4SDimitry Andric                                StringRef Segment, StringRef Section) {
1428480093f4SDimitry Andric   for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
1429480093f4SDimitry Andric                         Args.MakeArgString(Section), "0x4000"})
1430480093f4SDimitry Andric     CmdArgs.push_back(A);
1431480093f4SDimitry Andric }
1432480093f4SDimitry Andric 
14330b57cec5SDimitry Andric void Darwin::addProfileRTLibs(const ArgList &Args,
14340b57cec5SDimitry Andric                               ArgStringList &CmdArgs) const {
14355ffd83dbSDimitry Andric   if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
14365ffd83dbSDimitry Andric     return;
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   AddLinkRuntimeLib(Args, CmdArgs, "profile",
1439fe6060f1SDimitry Andric                     RuntimeLinkOptions(RLO_AlwaysLink));
14400b57cec5SDimitry Andric 
1441480093f4SDimitry Andric   bool ForGCOV = needsGCovInstrumentation(Args);
1442480093f4SDimitry Andric 
14430b57cec5SDimitry Andric   // If we have a symbol export directive and we're linking in the profile
14440b57cec5SDimitry Andric   // runtime, automatically export symbols necessary to implement some of the
14450b57cec5SDimitry Andric   // runtime's functionality.
1446bdd1243dSDimitry Andric   if (hasExportSymbolDirective(Args) && ForGCOV) {
1447e8d8bef9SDimitry Andric     addExportedSymbol(CmdArgs, "___gcov_dump");
1448e8d8bef9SDimitry Andric     addExportedSymbol(CmdArgs, "___gcov_reset");
14490b57cec5SDimitry Andric     addExportedSymbol(CmdArgs, "_writeout_fn_list");
1450d65cd7a5SDimitry Andric     addExportedSymbol(CmdArgs, "_reset_fn_list");
14510b57cec5SDimitry Andric   }
1452480093f4SDimitry Andric 
14535f757f3fSDimitry Andric   // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page
1454480093f4SDimitry Andric   // alignment. This allows profile counters to be mmap()'d to disk. Note that
1455480093f4SDimitry Andric   // it's not enough to just page-align __llvm_prf_cnts: the following section
1456480093f4SDimitry Andric   // must also be page-aligned so that its data is not clobbered by mmap().
1457480093f4SDimitry Andric   //
1458480093f4SDimitry Andric   // The section alignment is only needed when continuous profile sync is
1459480093f4SDimitry Andric   // enabled, but this is expected to be the default in Xcode. Specifying the
1460480093f4SDimitry Andric   // extra alignment also allows the same binary to be used with/without sync
1461480093f4SDimitry Andric   // enabled.
1462480093f4SDimitry Andric   if (!ForGCOV) {
14635f757f3fSDimitry Andric     for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {
1464480093f4SDimitry Andric       addSectalignToPage(
1465480093f4SDimitry Andric           Args, CmdArgs, "__DATA",
1466480093f4SDimitry Andric           llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
1467480093f4SDimitry Andric                                         /*AddSegmentInfo=*/false));
1468480093f4SDimitry Andric     }
1469480093f4SDimitry Andric   }
14700b57cec5SDimitry Andric }
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
14730b57cec5SDimitry Andric                                           ArgStringList &CmdArgs,
14740b57cec5SDimitry Andric                                           StringRef Sanitizer,
14750b57cec5SDimitry Andric                                           bool Shared) const {
14760b57cec5SDimitry Andric   auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
14770b57cec5SDimitry Andric   AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
14780b57cec5SDimitry Andric }
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
14810b57cec5SDimitry Andric     const ArgList &Args) const {
14820b57cec5SDimitry Andric   if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
14830b57cec5SDimitry Andric     StringRef Value = A->getValue();
1484bdd1243dSDimitry Andric     if (Value != "compiler-rt" && Value != "platform")
14850b57cec5SDimitry Andric       getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
14860b57cec5SDimitry Andric           << Value << "darwin";
14870b57cec5SDimitry Andric   }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric   return ToolChain::RLT_CompilerRT;
14900b57cec5SDimitry Andric }
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
14930b57cec5SDimitry Andric                                         ArgStringList &CmdArgs,
14940b57cec5SDimitry Andric                                         bool ForceLinkBuiltinRT) const {
14950b57cec5SDimitry Andric   // Call once to ensure diagnostic is printed if wrong value was specified
14960b57cec5SDimitry Andric   GetRuntimeLibType(Args);
14970b57cec5SDimitry Andric 
14980b57cec5SDimitry Andric   // Darwin doesn't support real static executables, don't link any runtime
14990b57cec5SDimitry Andric   // libraries with -static.
15000b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_static) ||
15010b57cec5SDimitry Andric       Args.hasArg(options::OPT_fapple_kext) ||
15020b57cec5SDimitry Andric       Args.hasArg(options::OPT_mkernel)) {
15030b57cec5SDimitry Andric     if (ForceLinkBuiltinRT)
15040b57cec5SDimitry Andric       AddLinkRuntimeLib(Args, CmdArgs, "builtins");
15050b57cec5SDimitry Andric     return;
15060b57cec5SDimitry Andric   }
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric   // Reject -static-libgcc for now, we can deal with this when and if someone
15090b57cec5SDimitry Andric   // cares. This is useful in situations where someone wants to statically link
15100b57cec5SDimitry Andric   // something like libstdc++, and needs its runtime support routines.
15110b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
15120b57cec5SDimitry Andric     getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
15130b57cec5SDimitry Andric     return;
15140b57cec5SDimitry Andric   }
15150b57cec5SDimitry Andric 
1516349cc55cSDimitry Andric   const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
1517bdd1243dSDimitry Andric 
151806c3fb27SDimitry Andric   if (!Sanitize.needsSharedRt()) {
151906c3fb27SDimitry Andric     const char *sanitizer = nullptr;
152006c3fb27SDimitry Andric     if (Sanitize.needsUbsanRt()) {
152106c3fb27SDimitry Andric       sanitizer = "UndefinedBehaviorSanitizer";
152206c3fb27SDimitry Andric     } else if (Sanitize.needsAsanRt()) {
152306c3fb27SDimitry Andric       sanitizer = "AddressSanitizer";
152406c3fb27SDimitry Andric     } else if (Sanitize.needsTsanRt()) {
152506c3fb27SDimitry Andric       sanitizer = "ThreadSanitizer";
152606c3fb27SDimitry Andric     }
152706c3fb27SDimitry Andric     if (sanitizer) {
152806c3fb27SDimitry Andric       getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)
152906c3fb27SDimitry Andric           << sanitizer;
1530bdd1243dSDimitry Andric       return;
1531bdd1243dSDimitry Andric     }
153206c3fb27SDimitry Andric   }
1533bdd1243dSDimitry Andric 
153406c3fb27SDimitry Andric   if (Sanitize.linkRuntimes()) {
153506c3fb27SDimitry Andric     if (Sanitize.needsAsanRt()) {
15365f757f3fSDimitry Andric       if (Sanitize.needsStableAbi()) {
15375f757f3fSDimitry Andric         AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);
15385f757f3fSDimitry Andric       } else {
153906c3fb27SDimitry Andric         assert(Sanitize.needsSharedRt() &&
154006c3fb27SDimitry Andric                "Static sanitizer runtimes not supported");
15410b57cec5SDimitry Andric         AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
154206c3fb27SDimitry Andric       }
15435f757f3fSDimitry Andric     }
15440b57cec5SDimitry Andric     if (Sanitize.needsLsanRt())
15450b57cec5SDimitry Andric       AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
1546bdd1243dSDimitry Andric     if (Sanitize.needsUbsanRt()) {
154706c3fb27SDimitry Andric       assert(Sanitize.needsSharedRt() &&
154806c3fb27SDimitry Andric              "Static sanitizer runtimes not supported");
154906c3fb27SDimitry Andric       AddLinkSanitizerLibArgs(
155006c3fb27SDimitry Andric           Args, CmdArgs,
155106c3fb27SDimitry Andric           Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");
1552bdd1243dSDimitry Andric     }
155306c3fb27SDimitry Andric     if (Sanitize.needsTsanRt()) {
155406c3fb27SDimitry Andric       assert(Sanitize.needsSharedRt() &&
155506c3fb27SDimitry Andric              "Static sanitizer runtimes not supported");
15560b57cec5SDimitry Andric       AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
155706c3fb27SDimitry Andric     }
15580b57cec5SDimitry Andric     if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
15590b57cec5SDimitry Andric       AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
15600b57cec5SDimitry Andric 
15610b57cec5SDimitry Andric         // Libfuzzer is written in C++ and requires libcxx.
15620b57cec5SDimitry Andric         AddCXXStdlibLibArgs(Args, CmdArgs);
15630b57cec5SDimitry Andric     }
15640b57cec5SDimitry Andric     if (Sanitize.needsStatsRt()) {
15650b57cec5SDimitry Andric       AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
15660b57cec5SDimitry Andric       AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
15670b57cec5SDimitry Andric     }
156806c3fb27SDimitry Andric   }
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric   const XRayArgs &XRay = getXRayArgs();
15710b57cec5SDimitry Andric   if (XRay.needsXRayRt()) {
15720b57cec5SDimitry Andric     AddLinkRuntimeLib(Args, CmdArgs, "xray");
15730b57cec5SDimitry Andric     AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
15740b57cec5SDimitry Andric     AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
15750b57cec5SDimitry Andric   }
15760b57cec5SDimitry Andric 
157781ad6265SDimitry Andric   if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {
157881ad6265SDimitry Andric     CmdArgs.push_back("-framework");
157981ad6265SDimitry Andric     CmdArgs.push_back("DriverKit");
158081ad6265SDimitry Andric   }
158181ad6265SDimitry Andric 
15820b57cec5SDimitry Andric   // Otherwise link libSystem, then the dynamic runtime library, and finally any
15830b57cec5SDimitry Andric   // target specific static runtime library.
158481ad6265SDimitry Andric   if (!isTargetDriverKit())
15850b57cec5SDimitry Andric     CmdArgs.push_back("-lSystem");
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric   // Select the dynamic runtime library and the target specific static library.
15880b57cec5SDimitry Andric   if (isTargetIOSBased()) {
15890b57cec5SDimitry Andric     // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
15900b57cec5SDimitry Andric     // it never went into the SDK.
15910b57cec5SDimitry Andric     // Linking against libgcc_s.1 isn't needed for iOS 5.0+
15920b57cec5SDimitry Andric     if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
15930b57cec5SDimitry Andric         getTriple().getArch() != llvm::Triple::aarch64)
15940b57cec5SDimitry Andric       CmdArgs.push_back("-lgcc_s.1");
15950b57cec5SDimitry Andric   }
15960b57cec5SDimitry Andric   AddLinkRuntimeLib(Args, CmdArgs, "builtins");
15970b57cec5SDimitry Andric }
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric /// Returns the most appropriate macOS target version for the current process.
16000b57cec5SDimitry Andric ///
16010b57cec5SDimitry Andric /// If the macOS SDK version is the same or earlier than the system version,
16020b57cec5SDimitry Andric /// then the SDK version is returned. Otherwise the system version is returned.
16030b57cec5SDimitry Andric static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
16040b57cec5SDimitry Andric   llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
16050b57cec5SDimitry Andric   if (!SystemTriple.isMacOSX())
16065ffd83dbSDimitry Andric     return std::string(MacOSSDKVersion);
16070eae32dcSDimitry Andric   VersionTuple SystemVersion;
16080eae32dcSDimitry Andric   SystemTriple.getMacOSXVersion(SystemVersion);
1609bdd1243dSDimitry Andric 
1610bdd1243dSDimitry Andric   unsigned Major, Minor, Micro;
16110b57cec5SDimitry Andric   bool HadExtra;
16120b57cec5SDimitry Andric   if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
16130b57cec5SDimitry Andric                                  HadExtra))
16145ffd83dbSDimitry Andric     return std::string(MacOSSDKVersion);
16150b57cec5SDimitry Andric   VersionTuple SDKVersion(Major, Minor, Micro);
1616bdd1243dSDimitry Andric 
16170b57cec5SDimitry Andric   if (SDKVersion > SystemVersion)
16180b57cec5SDimitry Andric     return SystemVersion.getAsString();
16195ffd83dbSDimitry Andric   return std::string(MacOSSDKVersion);
16200b57cec5SDimitry Andric }
16210b57cec5SDimitry Andric 
16220b57cec5SDimitry Andric namespace {
16230b57cec5SDimitry Andric 
16240b57cec5SDimitry Andric /// The Darwin OS that was selected or inferred from arguments / environment.
16250b57cec5SDimitry Andric struct DarwinPlatform {
16260b57cec5SDimitry Andric   enum SourceKind {
16270b57cec5SDimitry Andric     /// The OS was specified using the -target argument.
16280b57cec5SDimitry Andric     TargetArg,
1629349cc55cSDimitry Andric     /// The OS was specified using the -mtargetos= argument.
1630349cc55cSDimitry Andric     MTargetOSArg,
16310b57cec5SDimitry Andric     /// The OS was specified using the -m<os>-version-min argument.
16320b57cec5SDimitry Andric     OSVersionArg,
16330b57cec5SDimitry Andric     /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
16340b57cec5SDimitry Andric     DeploymentTargetEnv,
16350b57cec5SDimitry Andric     /// The OS was inferred from the SDK.
16360b57cec5SDimitry Andric     InferredFromSDK,
16370b57cec5SDimitry Andric     /// The OS was inferred from the -arch.
16380b57cec5SDimitry Andric     InferredFromArch
16390b57cec5SDimitry Andric   };
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   using DarwinPlatformKind = Darwin::DarwinPlatformKind;
16420b57cec5SDimitry Andric   using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric   DarwinPlatformKind getPlatform() const { return Platform; }
16450b57cec5SDimitry Andric 
16460b57cec5SDimitry Andric   DarwinEnvironmentKind getEnvironment() const { return Environment; }
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric   void setEnvironment(DarwinEnvironmentKind Kind) {
16490b57cec5SDimitry Andric     Environment = Kind;
16500b57cec5SDimitry Andric     InferSimulatorFromArch = false;
16510b57cec5SDimitry Andric   }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric   StringRef getOSVersion() const {
16540b57cec5SDimitry Andric     if (Kind == OSVersionArg)
16550b57cec5SDimitry Andric       return Argument->getValue();
16560b57cec5SDimitry Andric     return OSVersion;
16570b57cec5SDimitry Andric   }
16580b57cec5SDimitry Andric 
16590b57cec5SDimitry Andric   void setOSVersion(StringRef S) {
16600b57cec5SDimitry Andric     assert(Kind == TargetArg && "Unexpected kind!");
16615ffd83dbSDimitry Andric     OSVersion = std::string(S);
16620b57cec5SDimitry Andric   }
16630b57cec5SDimitry Andric 
16640b57cec5SDimitry Andric   bool hasOSVersion() const { return HasOSVersion; }
16650b57cec5SDimitry Andric 
1666fe6060f1SDimitry Andric   VersionTuple getNativeTargetVersion() const {
1667fe6060f1SDimitry Andric     assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
1668fe6060f1SDimitry Andric            "native target version is specified only for Mac Catalyst");
1669fe6060f1SDimitry Andric     return NativeTargetVersion;
1670fe6060f1SDimitry Andric   }
1671fe6060f1SDimitry Andric 
16720b57cec5SDimitry Andric   /// Returns true if the target OS was explicitly specified.
16730b57cec5SDimitry Andric   bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
16740b57cec5SDimitry Andric 
16750b57cec5SDimitry Andric   /// Returns true if the simulator environment can be inferred from the arch.
16760b57cec5SDimitry Andric   bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
16770b57cec5SDimitry Andric 
1678bdd1243dSDimitry Andric   const std::optional<llvm::Triple> &getTargetVariantTriple() const {
167981ad6265SDimitry Andric     return TargetVariantTriple;
168081ad6265SDimitry Andric   }
168181ad6265SDimitry Andric 
16820b57cec5SDimitry Andric   /// Adds the -m<os>-version-min argument to the compiler invocation.
16830b57cec5SDimitry Andric   void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
16840b57cec5SDimitry Andric     if (Argument)
16850b57cec5SDimitry Andric       return;
1686349cc55cSDimitry Andric     assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&
1687349cc55cSDimitry Andric            "Invalid kind");
16880b57cec5SDimitry Andric     options::ID Opt;
16890b57cec5SDimitry Andric     switch (Platform) {
16900b57cec5SDimitry Andric     case DarwinPlatformKind::MacOS:
1691753f127fSDimitry Andric       Opt = options::OPT_mmacos_version_min_EQ;
16920b57cec5SDimitry Andric       break;
16930b57cec5SDimitry Andric     case DarwinPlatformKind::IPhoneOS:
1694753f127fSDimitry Andric       Opt = options::OPT_mios_version_min_EQ;
16950b57cec5SDimitry Andric       break;
16960b57cec5SDimitry Andric     case DarwinPlatformKind::TvOS:
16970b57cec5SDimitry Andric       Opt = options::OPT_mtvos_version_min_EQ;
16980b57cec5SDimitry Andric       break;
16990b57cec5SDimitry Andric     case DarwinPlatformKind::WatchOS:
17000b57cec5SDimitry Andric       Opt = options::OPT_mwatchos_version_min_EQ;
17010b57cec5SDimitry Andric       break;
17027a6dacacSDimitry Andric     case DarwinPlatformKind::XROS:
17037a6dacacSDimitry Andric       // xrOS always explicitly provides a version in the triple.
17047a6dacacSDimitry Andric       return;
170581ad6265SDimitry Andric     case DarwinPlatformKind::DriverKit:
170681ad6265SDimitry Andric       // DriverKit always explicitly provides a version in the triple.
170781ad6265SDimitry Andric       return;
17080b57cec5SDimitry Andric     }
17090b57cec5SDimitry Andric     Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
17100b57cec5SDimitry Andric     Args.append(Argument);
17110b57cec5SDimitry Andric   }
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric   /// Returns the OS version with the argument / environment variable that
17140b57cec5SDimitry Andric   /// specified it.
17150b57cec5SDimitry Andric   std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
17160b57cec5SDimitry Andric     switch (Kind) {
17170b57cec5SDimitry Andric     case TargetArg:
1718349cc55cSDimitry Andric     case MTargetOSArg:
17190b57cec5SDimitry Andric     case OSVersionArg:
17200b57cec5SDimitry Andric     case InferredFromSDK:
17210b57cec5SDimitry Andric     case InferredFromArch:
17220b57cec5SDimitry Andric       assert(Argument && "OS version argument not yet inferred");
17230b57cec5SDimitry Andric       return Argument->getAsString(Args);
17240b57cec5SDimitry Andric     case DeploymentTargetEnv:
17250b57cec5SDimitry Andric       return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
17260b57cec5SDimitry Andric     }
17270b57cec5SDimitry Andric     llvm_unreachable("Unsupported Darwin Source Kind");
17280b57cec5SDimitry Andric   }
17290b57cec5SDimitry Andric 
1730349cc55cSDimitry Andric   void setEnvironment(llvm::Triple::EnvironmentType EnvType,
1731349cc55cSDimitry Andric                       const VersionTuple &OSVersion,
1732bdd1243dSDimitry Andric                       const std::optional<DarwinSDKInfo> &SDKInfo) {
1733349cc55cSDimitry Andric     switch (EnvType) {
1734349cc55cSDimitry Andric     case llvm::Triple::Simulator:
1735349cc55cSDimitry Andric       Environment = DarwinEnvironmentKind::Simulator;
1736349cc55cSDimitry Andric       break;
1737349cc55cSDimitry Andric     case llvm::Triple::MacABI: {
1738349cc55cSDimitry Andric       Environment = DarwinEnvironmentKind::MacCatalyst;
1739349cc55cSDimitry Andric       // The minimum native macOS target for MacCatalyst is macOS 10.15.
1740349cc55cSDimitry Andric       NativeTargetVersion = VersionTuple(10, 15);
1741349cc55cSDimitry Andric       if (HasOSVersion && SDKInfo) {
1742349cc55cSDimitry Andric         if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
1743349cc55cSDimitry Andric                 DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
1744349cc55cSDimitry Andric           if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
1745bdd1243dSDimitry Andric                   OSVersion, NativeTargetVersion, std::nullopt)) {
1746349cc55cSDimitry Andric             NativeTargetVersion = *MacOSVersion;
1747349cc55cSDimitry Andric           }
1748349cc55cSDimitry Andric         }
1749349cc55cSDimitry Andric       }
175081ad6265SDimitry Andric       // In a zippered build, we could be building for a macOS target that's
175181ad6265SDimitry Andric       // lower than the version that's implied by the OS version. In that case
175281ad6265SDimitry Andric       // we need to use the minimum version as the native target version.
175381ad6265SDimitry Andric       if (TargetVariantTriple) {
175481ad6265SDimitry Andric         auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
175581ad6265SDimitry Andric         if (TargetVariantVersion.getMajor()) {
175681ad6265SDimitry Andric           if (TargetVariantVersion < NativeTargetVersion)
175781ad6265SDimitry Andric             NativeTargetVersion = TargetVariantVersion;
175881ad6265SDimitry Andric         }
175981ad6265SDimitry Andric       }
1760349cc55cSDimitry Andric       break;
1761349cc55cSDimitry Andric     }
1762349cc55cSDimitry Andric     default:
1763349cc55cSDimitry Andric       break;
1764349cc55cSDimitry Andric     }
1765349cc55cSDimitry Andric   }
1766349cc55cSDimitry Andric 
1767fe6060f1SDimitry Andric   static DarwinPlatform
1768fe6060f1SDimitry Andric   createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
1769bdd1243dSDimitry Andric                    std::optional<llvm::Triple> TargetVariantTriple,
1770bdd1243dSDimitry Andric                    const std::optional<DarwinSDKInfo> &SDKInfo) {
17710b57cec5SDimitry Andric     DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
17720b57cec5SDimitry Andric                           A);
17730eae32dcSDimitry Andric     VersionTuple OsVersion = TT.getOSVersion();
17740eae32dcSDimitry Andric     if (OsVersion.getMajor() == 0)
17750b57cec5SDimitry Andric       Result.HasOSVersion = false;
177681ad6265SDimitry Andric     Result.TargetVariantTriple = TargetVariantTriple;
17770eae32dcSDimitry Andric     Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
1778349cc55cSDimitry Andric     return Result;
1779fe6060f1SDimitry Andric   }
1780349cc55cSDimitry Andric   static DarwinPlatform
1781349cc55cSDimitry Andric   createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
1782349cc55cSDimitry Andric                       llvm::Triple::EnvironmentType Environment, Arg *A,
1783bdd1243dSDimitry Andric                       const std::optional<DarwinSDKInfo> &SDKInfo) {
1784349cc55cSDimitry Andric     DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
1785349cc55cSDimitry Andric                           OSVersion.getAsString(), A);
1786349cc55cSDimitry Andric     Result.InferSimulatorFromArch = false;
1787349cc55cSDimitry Andric     Result.setEnvironment(Environment, OSVersion, SDKInfo);
17880b57cec5SDimitry Andric     return Result;
17890b57cec5SDimitry Andric   }
1790bdd1243dSDimitry Andric   static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
1791bdd1243dSDimitry Andric                                            bool IsSimulator) {
1792bdd1243dSDimitry Andric     DarwinPlatform Result{OSVersionArg, Platform, A};
1793bdd1243dSDimitry Andric     if (IsSimulator)
1794bdd1243dSDimitry Andric       Result.Environment = DarwinEnvironmentKind::Simulator;
1795bdd1243dSDimitry Andric     return Result;
17960b57cec5SDimitry Andric   }
17970b57cec5SDimitry Andric   static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
17980b57cec5SDimitry Andric                                                   StringRef EnvVarName,
17990b57cec5SDimitry Andric                                                   StringRef Value) {
18000b57cec5SDimitry Andric     DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
18010b57cec5SDimitry Andric     Result.EnvVarName = EnvVarName;
18020b57cec5SDimitry Andric     return Result;
18030b57cec5SDimitry Andric   }
18040b57cec5SDimitry Andric   static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
18050b57cec5SDimitry Andric                                       StringRef Value,
18060b57cec5SDimitry Andric                                       bool IsSimulator = false) {
18070b57cec5SDimitry Andric     DarwinPlatform Result(InferredFromSDK, Platform, Value);
18080b57cec5SDimitry Andric     if (IsSimulator)
18090b57cec5SDimitry Andric       Result.Environment = DarwinEnvironmentKind::Simulator;
18100b57cec5SDimitry Andric     Result.InferSimulatorFromArch = false;
18110b57cec5SDimitry Andric     return Result;
18120b57cec5SDimitry Andric   }
18130b57cec5SDimitry Andric   static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
18140b57cec5SDimitry Andric                                        StringRef Value) {
18150b57cec5SDimitry Andric     return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
18160b57cec5SDimitry Andric   }
18170b57cec5SDimitry Andric 
18180b57cec5SDimitry Andric   /// Constructs an inferred SDKInfo value based on the version inferred from
18190b57cec5SDimitry Andric   /// the SDK path itself. Only works for values that were created by inferring
18200b57cec5SDimitry Andric   /// the platform from the SDKPath.
18210b57cec5SDimitry Andric   DarwinSDKInfo inferSDKInfo() {
18220b57cec5SDimitry Andric     assert(Kind == InferredFromSDK && "can infer SDK info only");
18230b57cec5SDimitry Andric     llvm::VersionTuple Version;
18240b57cec5SDimitry Andric     bool IsValid = !Version.tryParse(OSVersion);
18250b57cec5SDimitry Andric     (void)IsValid;
18260b57cec5SDimitry Andric     assert(IsValid && "invalid SDK version");
1827fe6060f1SDimitry Andric     return DarwinSDKInfo(
1828fe6060f1SDimitry Andric         Version,
1829fe6060f1SDimitry Andric         /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));
18300b57cec5SDimitry Andric   }
18310b57cec5SDimitry Andric 
18320b57cec5SDimitry Andric private:
18330b57cec5SDimitry Andric   DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
18340b57cec5SDimitry Andric       : Kind(Kind), Platform(Platform), Argument(Argument) {}
18350b57cec5SDimitry Andric   DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
18360b57cec5SDimitry Andric                  Arg *Argument = nullptr)
18370b57cec5SDimitry Andric       : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
18380b57cec5SDimitry Andric 
18390b57cec5SDimitry Andric   static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
18400b57cec5SDimitry Andric     switch (OS) {
18410b57cec5SDimitry Andric     case llvm::Triple::Darwin:
18420b57cec5SDimitry Andric     case llvm::Triple::MacOSX:
18430b57cec5SDimitry Andric       return DarwinPlatformKind::MacOS;
18440b57cec5SDimitry Andric     case llvm::Triple::IOS:
18450b57cec5SDimitry Andric       return DarwinPlatformKind::IPhoneOS;
18460b57cec5SDimitry Andric     case llvm::Triple::TvOS:
18470b57cec5SDimitry Andric       return DarwinPlatformKind::TvOS;
18480b57cec5SDimitry Andric     case llvm::Triple::WatchOS:
18490b57cec5SDimitry Andric       return DarwinPlatformKind::WatchOS;
18507a6dacacSDimitry Andric     case llvm::Triple::XROS:
18517a6dacacSDimitry Andric       return DarwinPlatformKind::XROS;
185281ad6265SDimitry Andric     case llvm::Triple::DriverKit:
185381ad6265SDimitry Andric       return DarwinPlatformKind::DriverKit;
18540b57cec5SDimitry Andric     default:
18550b57cec5SDimitry Andric       llvm_unreachable("Unable to infer Darwin variant");
18560b57cec5SDimitry Andric     }
18570b57cec5SDimitry Andric   }
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   SourceKind Kind;
18600b57cec5SDimitry Andric   DarwinPlatformKind Platform;
18610b57cec5SDimitry Andric   DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
1862fe6060f1SDimitry Andric   VersionTuple NativeTargetVersion;
18630b57cec5SDimitry Andric   std::string OSVersion;
18640b57cec5SDimitry Andric   bool HasOSVersion = true, InferSimulatorFromArch = true;
18650b57cec5SDimitry Andric   Arg *Argument;
18660b57cec5SDimitry Andric   StringRef EnvVarName;
1867bdd1243dSDimitry Andric   std::optional<llvm::Triple> TargetVariantTriple;
18680b57cec5SDimitry Andric };
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric /// Returns the deployment target that's specified using the -m<os>-version-min
18710b57cec5SDimitry Andric /// argument.
1872bdd1243dSDimitry Andric std::optional<DarwinPlatform>
18730b57cec5SDimitry Andric getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
18740b57cec5SDimitry Andric                                     const Driver &TheDriver) {
1875753f127fSDimitry Andric   Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
1876753f127fSDimitry Andric   Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
18770b57cec5SDimitry Andric                                     options::OPT_mios_simulator_version_min_EQ);
18780b57cec5SDimitry Andric   Arg *TvOSVersion =
18790b57cec5SDimitry Andric       Args.getLastArg(options::OPT_mtvos_version_min_EQ,
18800b57cec5SDimitry Andric                       options::OPT_mtvos_simulator_version_min_EQ);
18810b57cec5SDimitry Andric   Arg *WatchOSVersion =
18820b57cec5SDimitry Andric       Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
18830b57cec5SDimitry Andric                       options::OPT_mwatchos_simulator_version_min_EQ);
1884753f127fSDimitry Andric   if (macOSVersion) {
18850b57cec5SDimitry Andric     if (iOSVersion || TvOSVersion || WatchOSVersion) {
18860b57cec5SDimitry Andric       TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1887753f127fSDimitry Andric           << macOSVersion->getAsString(Args)
18880b57cec5SDimitry Andric           << (iOSVersion ? iOSVersion
18890b57cec5SDimitry Andric                          : TvOSVersion ? TvOSVersion : WatchOSVersion)
18900b57cec5SDimitry Andric                  ->getAsString(Args);
18910b57cec5SDimitry Andric     }
1892bdd1243dSDimitry Andric     return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,
189306c3fb27SDimitry Andric                                               /*IsSimulator=*/false);
18940b57cec5SDimitry Andric   } else if (iOSVersion) {
18950b57cec5SDimitry Andric     if (TvOSVersion || WatchOSVersion) {
18960b57cec5SDimitry Andric       TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
18970b57cec5SDimitry Andric           << iOSVersion->getAsString(Args)
18980b57cec5SDimitry Andric           << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
18990b57cec5SDimitry Andric     }
1900bdd1243dSDimitry Andric     return DarwinPlatform::createOSVersionArg(
1901bdd1243dSDimitry Andric         Darwin::IPhoneOS, iOSVersion,
1902bdd1243dSDimitry Andric         iOSVersion->getOption().getID() ==
1903bdd1243dSDimitry Andric             options::OPT_mios_simulator_version_min_EQ);
19040b57cec5SDimitry Andric   } else if (TvOSVersion) {
19050b57cec5SDimitry Andric     if (WatchOSVersion) {
19060b57cec5SDimitry Andric       TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
19070b57cec5SDimitry Andric           << TvOSVersion->getAsString(Args)
19080b57cec5SDimitry Andric           << WatchOSVersion->getAsString(Args);
19090b57cec5SDimitry Andric     }
1910bdd1243dSDimitry Andric     return DarwinPlatform::createOSVersionArg(
1911bdd1243dSDimitry Andric         Darwin::TvOS, TvOSVersion,
1912bdd1243dSDimitry Andric         TvOSVersion->getOption().getID() ==
1913bdd1243dSDimitry Andric             options::OPT_mtvos_simulator_version_min_EQ);
19140b57cec5SDimitry Andric   } else if (WatchOSVersion)
1915bdd1243dSDimitry Andric     return DarwinPlatform::createOSVersionArg(
1916bdd1243dSDimitry Andric         Darwin::WatchOS, WatchOSVersion,
1917bdd1243dSDimitry Andric         WatchOSVersion->getOption().getID() ==
1918bdd1243dSDimitry Andric             options::OPT_mwatchos_simulator_version_min_EQ);
1919bdd1243dSDimitry Andric   return std::nullopt;
19200b57cec5SDimitry Andric }
19210b57cec5SDimitry Andric 
19220b57cec5SDimitry Andric /// Returns the deployment target that's specified using the
19230b57cec5SDimitry Andric /// OS_DEPLOYMENT_TARGET environment variable.
1924bdd1243dSDimitry Andric std::optional<DarwinPlatform>
19250b57cec5SDimitry Andric getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
19260b57cec5SDimitry Andric                                             const llvm::Triple &Triple) {
19270b57cec5SDimitry Andric   std::string Targets[Darwin::LastDarwinPlatform + 1];
19280b57cec5SDimitry Andric   const char *EnvVars[] = {
19290b57cec5SDimitry Andric       "MACOSX_DEPLOYMENT_TARGET",
19300b57cec5SDimitry Andric       "IPHONEOS_DEPLOYMENT_TARGET",
19310b57cec5SDimitry Andric       "TVOS_DEPLOYMENT_TARGET",
19320b57cec5SDimitry Andric       "WATCHOS_DEPLOYMENT_TARGET",
193381ad6265SDimitry Andric       "DRIVERKIT_DEPLOYMENT_TARGET",
19340fca6ea1SDimitry Andric       "XROS_DEPLOYMENT_TARGET"
19350b57cec5SDimitry Andric   };
1936bdd1243dSDimitry Andric   static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,
19370b57cec5SDimitry Andric                 "Missing platform");
1938bdd1243dSDimitry Andric   for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {
19390b57cec5SDimitry Andric     if (char *Env = ::getenv(I.value()))
19400b57cec5SDimitry Andric       Targets[I.index()] = Env;
19410b57cec5SDimitry Andric   }
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric   // Allow conflicts among OSX and iOS for historical reasons, but choose the
19440b57cec5SDimitry Andric   // default platform.
19450b57cec5SDimitry Andric   if (!Targets[Darwin::MacOS].empty() &&
19460b57cec5SDimitry Andric       (!Targets[Darwin::IPhoneOS].empty() ||
19470fca6ea1SDimitry Andric        !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() ||
19480fca6ea1SDimitry Andric        !Targets[Darwin::XROS].empty())) {
19490b57cec5SDimitry Andric     if (Triple.getArch() == llvm::Triple::arm ||
19500b57cec5SDimitry Andric         Triple.getArch() == llvm::Triple::aarch64 ||
19510b57cec5SDimitry Andric         Triple.getArch() == llvm::Triple::thumb)
19520b57cec5SDimitry Andric       Targets[Darwin::MacOS] = "";
19530b57cec5SDimitry Andric     else
19540b57cec5SDimitry Andric       Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
19550fca6ea1SDimitry Andric           Targets[Darwin::TvOS] = Targets[Darwin::XROS] = "";
1956a7dea167SDimitry Andric   } else {
1957a7dea167SDimitry Andric     // Don't allow conflicts in any other platform.
1958bdd1243dSDimitry Andric     unsigned FirstTarget = std::size(Targets);
1959bdd1243dSDimitry Andric     for (unsigned I = 0; I != std::size(Targets); ++I) {
1960a7dea167SDimitry Andric       if (Targets[I].empty())
1961a7dea167SDimitry Andric         continue;
1962bdd1243dSDimitry Andric       if (FirstTarget == std::size(Targets))
1963a7dea167SDimitry Andric         FirstTarget = I;
1964a7dea167SDimitry Andric       else
1965a7dea167SDimitry Andric         TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
1966a7dea167SDimitry Andric             << Targets[FirstTarget] << Targets[I];
1967a7dea167SDimitry Andric     }
19680b57cec5SDimitry Andric   }
19690b57cec5SDimitry Andric 
1970bdd1243dSDimitry Andric   for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {
19710b57cec5SDimitry Andric     if (!Target.value().empty())
19720b57cec5SDimitry Andric       return DarwinPlatform::createDeploymentTargetEnv(
19730b57cec5SDimitry Andric           (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
19740b57cec5SDimitry Andric           Target.value());
19750b57cec5SDimitry Andric   }
1976bdd1243dSDimitry Andric   return std::nullopt;
19770b57cec5SDimitry Andric }
19780b57cec5SDimitry Andric 
1979fe6060f1SDimitry Andric /// Returns the SDK name without the optional prefix that ends with a '.' or an
1980fe6060f1SDimitry Andric /// empty string otherwise.
1981fe6060f1SDimitry Andric static StringRef dropSDKNamePrefix(StringRef SDKName) {
1982fe6060f1SDimitry Andric   size_t PrefixPos = SDKName.find('.');
1983fe6060f1SDimitry Andric   if (PrefixPos == StringRef::npos)
1984fe6060f1SDimitry Andric     return "";
1985fe6060f1SDimitry Andric   return SDKName.substr(PrefixPos + 1);
1986fe6060f1SDimitry Andric }
1987fe6060f1SDimitry Andric 
19880b57cec5SDimitry Andric /// Tries to infer the deployment target from the SDK specified by -isysroot
19890b57cec5SDimitry Andric /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
19900b57cec5SDimitry Andric /// it's available.
1991bdd1243dSDimitry Andric std::optional<DarwinPlatform>
19920b57cec5SDimitry Andric inferDeploymentTargetFromSDK(DerivedArgList &Args,
1993bdd1243dSDimitry Andric                              const std::optional<DarwinSDKInfo> &SDKInfo) {
19940b57cec5SDimitry Andric   const Arg *A = Args.getLastArg(options::OPT_isysroot);
19950b57cec5SDimitry Andric   if (!A)
1996bdd1243dSDimitry Andric     return std::nullopt;
19970b57cec5SDimitry Andric   StringRef isysroot = A->getValue();
19980b57cec5SDimitry Andric   StringRef SDK = Darwin::getSDKName(isysroot);
19990b57cec5SDimitry Andric   if (!SDK.size())
2000bdd1243dSDimitry Andric     return std::nullopt;
20010b57cec5SDimitry Andric 
20020b57cec5SDimitry Andric   std::string Version;
20030b57cec5SDimitry Andric   if (SDKInfo) {
20040b57cec5SDimitry Andric     // Get the version from the SDKSettings.json if it's available.
20050b57cec5SDimitry Andric     Version = SDKInfo->getVersion().getAsString();
20060b57cec5SDimitry Andric   } else {
20070b57cec5SDimitry Andric     // Slice the version number out.
20080b57cec5SDimitry Andric     // Version number is between the first and the last number.
20090b57cec5SDimitry Andric     size_t StartVer = SDK.find_first_of("0123456789");
20100b57cec5SDimitry Andric     size_t EndVer = SDK.find_last_of("0123456789");
20110b57cec5SDimitry Andric     if (StartVer != StringRef::npos && EndVer > StartVer)
20125ffd83dbSDimitry Andric       Version = std::string(SDK.slice(StartVer, EndVer + 1));
20130b57cec5SDimitry Andric   }
20140b57cec5SDimitry Andric   if (Version.empty())
2015bdd1243dSDimitry Andric     return std::nullopt;
20160b57cec5SDimitry Andric 
2017fe6060f1SDimitry Andric   auto CreatePlatformFromSDKName =
2018bdd1243dSDimitry Andric       [&](StringRef SDK) -> std::optional<DarwinPlatform> {
20195f757f3fSDimitry Andric     if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator"))
20200b57cec5SDimitry Andric       return DarwinPlatform::createFromSDK(
20210b57cec5SDimitry Andric           Darwin::IPhoneOS, Version,
20225f757f3fSDimitry Andric           /*IsSimulator=*/SDK.starts_with("iPhoneSimulator"));
20235f757f3fSDimitry Andric     else if (SDK.starts_with("MacOSX"))
20240b57cec5SDimitry Andric       return DarwinPlatform::createFromSDK(Darwin::MacOS,
20250b57cec5SDimitry Andric                                            getSystemOrSDKMacOSVersion(Version));
20265f757f3fSDimitry Andric     else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator"))
20270b57cec5SDimitry Andric       return DarwinPlatform::createFromSDK(
20280b57cec5SDimitry Andric           Darwin::WatchOS, Version,
20295f757f3fSDimitry Andric           /*IsSimulator=*/SDK.starts_with("WatchSimulator"));
20305f757f3fSDimitry Andric     else if (SDK.starts_with("AppleTVOS") ||
20315f757f3fSDimitry Andric              SDK.starts_with("AppleTVSimulator"))
20320b57cec5SDimitry Andric       return DarwinPlatform::createFromSDK(
20330b57cec5SDimitry Andric           Darwin::TvOS, Version,
20345f757f3fSDimitry Andric           /*IsSimulator=*/SDK.starts_with("AppleTVSimulator"));
20357a6dacacSDimitry Andric     else if (SDK.starts_with("XR"))
20367a6dacacSDimitry Andric       return DarwinPlatform::createFromSDK(
20377a6dacacSDimitry Andric           Darwin::XROS, Version,
20387a6dacacSDimitry Andric           /*IsSimulator=*/SDK.contains("Simulator"));
20395f757f3fSDimitry Andric     else if (SDK.starts_with("DriverKit"))
204081ad6265SDimitry Andric       return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);
2041bdd1243dSDimitry Andric     return std::nullopt;
2042fe6060f1SDimitry Andric   };
2043fe6060f1SDimitry Andric   if (auto Result = CreatePlatformFromSDKName(SDK))
2044fe6060f1SDimitry Andric     return Result;
2045fe6060f1SDimitry Andric   // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
2046fe6060f1SDimitry Andric   return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric 
20490b57cec5SDimitry Andric std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
20500b57cec5SDimitry Andric                          const Driver &TheDriver) {
20510eae32dcSDimitry Andric   VersionTuple OsVersion;
20520b57cec5SDimitry Andric   llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
20530b57cec5SDimitry Andric   switch (OS) {
20540b57cec5SDimitry Andric   case llvm::Triple::Darwin:
20550b57cec5SDimitry Andric   case llvm::Triple::MacOSX:
20560b57cec5SDimitry Andric     // If there is no version specified on triple, and both host and target are
20570b57cec5SDimitry Andric     // macos, use the host triple to infer OS version.
20580b57cec5SDimitry Andric     if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
20590b57cec5SDimitry Andric         !Triple.getOSMajorVersion())
20600eae32dcSDimitry Andric       SystemTriple.getMacOSXVersion(OsVersion);
20610eae32dcSDimitry Andric     else if (!Triple.getMacOSXVersion(OsVersion))
20620b57cec5SDimitry Andric       TheDriver.Diag(diag::err_drv_invalid_darwin_version)
20630b57cec5SDimitry Andric           << Triple.getOSName();
20640b57cec5SDimitry Andric     break;
20650b57cec5SDimitry Andric   case llvm::Triple::IOS:
2066349cc55cSDimitry Andric     if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
20670eae32dcSDimitry Andric       OsVersion = VersionTuple(13, 1);
2068349cc55cSDimitry Andric     } else
20690eae32dcSDimitry Andric       OsVersion = Triple.getiOSVersion();
20700b57cec5SDimitry Andric     break;
20710b57cec5SDimitry Andric   case llvm::Triple::TvOS:
20720eae32dcSDimitry Andric     OsVersion = Triple.getOSVersion();
20730b57cec5SDimitry Andric     break;
20740b57cec5SDimitry Andric   case llvm::Triple::WatchOS:
20750eae32dcSDimitry Andric     OsVersion = Triple.getWatchOSVersion();
20760b57cec5SDimitry Andric     break;
20777a6dacacSDimitry Andric   case llvm::Triple::XROS:
20787a6dacacSDimitry Andric     OsVersion = Triple.getOSVersion();
20797a6dacacSDimitry Andric     if (!OsVersion.getMajor())
20807a6dacacSDimitry Andric       OsVersion = OsVersion.withMajorReplaced(1);
20817a6dacacSDimitry Andric     break;
208281ad6265SDimitry Andric   case llvm::Triple::DriverKit:
208381ad6265SDimitry Andric     OsVersion = Triple.getDriverKitVersion();
208481ad6265SDimitry Andric     break;
20850b57cec5SDimitry Andric   default:
20860b57cec5SDimitry Andric     llvm_unreachable("Unexpected OS type");
20870b57cec5SDimitry Andric     break;
20880b57cec5SDimitry Andric   }
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric   std::string OSVersion;
20910eae32dcSDimitry Andric   llvm::raw_string_ostream(OSVersion)
209281ad6265SDimitry Andric       << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
209381ad6265SDimitry Andric       << OsVersion.getSubminor().value_or(0);
20940b57cec5SDimitry Andric   return OSVersion;
20950b57cec5SDimitry Andric }
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric /// Tries to infer the target OS from the -arch.
2098bdd1243dSDimitry Andric std::optional<DarwinPlatform>
20990b57cec5SDimitry Andric inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
21000b57cec5SDimitry Andric                               const llvm::Triple &Triple,
21010b57cec5SDimitry Andric                               const Driver &TheDriver) {
21020b57cec5SDimitry Andric   llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
21030b57cec5SDimitry Andric 
21040b57cec5SDimitry Andric   StringRef MachOArchName = Toolchain.getMachOArchName(Args);
210581ad6265SDimitry Andric   if (MachOArchName == "arm64" || MachOArchName == "arm64e")
21065ffd83dbSDimitry Andric     OSTy = llvm::Triple::MacOSX;
210781ad6265SDimitry Andric   else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
21080b57cec5SDimitry Andric     OSTy = llvm::Triple::IOS;
2109480093f4SDimitry Andric   else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
21100b57cec5SDimitry Andric     OSTy = llvm::Triple::WatchOS;
21110b57cec5SDimitry Andric   else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
21120b57cec5SDimitry Andric            MachOArchName != "armv7em")
21130b57cec5SDimitry Andric     OSTy = llvm::Triple::MacOSX;
21140b57cec5SDimitry Andric   if (OSTy == llvm::Triple::UnknownOS)
2115bdd1243dSDimitry Andric     return std::nullopt;
21160b57cec5SDimitry Andric   return DarwinPlatform::createFromArch(OSTy,
21170b57cec5SDimitry Andric                                         getOSVersion(OSTy, Triple, TheDriver));
21180b57cec5SDimitry Andric }
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric /// Returns the deployment target that's specified using the -target option.
2121bdd1243dSDimitry Andric std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
2122fe6060f1SDimitry Andric     DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
2123bdd1243dSDimitry Andric     const std::optional<DarwinSDKInfo> &SDKInfo) {
21240b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_target))
2125bdd1243dSDimitry Andric     return std::nullopt;
21260b57cec5SDimitry Andric   if (Triple.getOS() == llvm::Triple::Darwin ||
21270b57cec5SDimitry Andric       Triple.getOS() == llvm::Triple::UnknownOS)
2128bdd1243dSDimitry Andric     return std::nullopt;
21290b57cec5SDimitry Andric   std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
2130bdd1243dSDimitry Andric   std::optional<llvm::Triple> TargetVariantTriple;
213181ad6265SDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
213281ad6265SDimitry Andric     llvm::Triple TVT(A->getValue());
213381ad6265SDimitry Andric     // Find a matching <arch>-<vendor> target variant triple that can be used.
213481ad6265SDimitry Andric     if ((Triple.getArch() == llvm::Triple::aarch64 ||
213581ad6265SDimitry Andric          TVT.getArchName() == Triple.getArchName()) &&
213681ad6265SDimitry Andric         TVT.getArch() == Triple.getArch() &&
213781ad6265SDimitry Andric         TVT.getSubArch() == Triple.getSubArch() &&
213881ad6265SDimitry Andric         TVT.getVendor() == Triple.getVendor()) {
213981ad6265SDimitry Andric       if (TargetVariantTriple)
214081ad6265SDimitry Andric         continue;
214181ad6265SDimitry Andric       A->claim();
214281ad6265SDimitry Andric       // Accept a -target-variant triple when compiling code that may run on
21435f757f3fSDimitry Andric       // macOS or Mac Catalyst.
214481ad6265SDimitry Andric       if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
214581ad6265SDimitry Andric            TVT.isMacCatalystEnvironment()) ||
214681ad6265SDimitry Andric           (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
214781ad6265SDimitry Andric            Triple.isMacCatalystEnvironment())) {
214881ad6265SDimitry Andric         TargetVariantTriple = TVT;
214981ad6265SDimitry Andric         continue;
215081ad6265SDimitry Andric       }
215181ad6265SDimitry Andric       TheDriver.Diag(diag::err_drv_target_variant_invalid)
215281ad6265SDimitry Andric           << A->getSpelling() << A->getValue();
215381ad6265SDimitry Andric     }
215481ad6265SDimitry Andric   }
215581ad6265SDimitry Andric   return DarwinPlatform::createFromTarget(Triple, OSVersion,
215681ad6265SDimitry Andric                                           Args.getLastArg(options::OPT_target),
215781ad6265SDimitry Andric                                           TargetVariantTriple, SDKInfo);
21580b57cec5SDimitry Andric }
21590b57cec5SDimitry Andric 
2160349cc55cSDimitry Andric /// Returns the deployment target that's specified using the -mtargetos option.
2161bdd1243dSDimitry Andric std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
2162bdd1243dSDimitry Andric     DerivedArgList &Args, const Driver &TheDriver,
2163bdd1243dSDimitry Andric     const std::optional<DarwinSDKInfo> &SDKInfo) {
2164349cc55cSDimitry Andric   auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
2165349cc55cSDimitry Andric   if (!A)
2166bdd1243dSDimitry Andric     return std::nullopt;
2167349cc55cSDimitry Andric   llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
2168349cc55cSDimitry Andric   switch (TT.getOS()) {
2169349cc55cSDimitry Andric   case llvm::Triple::MacOSX:
2170349cc55cSDimitry Andric   case llvm::Triple::IOS:
2171349cc55cSDimitry Andric   case llvm::Triple::TvOS:
2172349cc55cSDimitry Andric   case llvm::Triple::WatchOS:
21737a6dacacSDimitry Andric   case llvm::Triple::XROS:
2174349cc55cSDimitry Andric     break;
2175349cc55cSDimitry Andric   default:
2176349cc55cSDimitry Andric     TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
2177349cc55cSDimitry Andric         << TT.getOSName() << A->getAsString(Args);
2178bdd1243dSDimitry Andric     return std::nullopt;
2179349cc55cSDimitry Andric   }
2180349cc55cSDimitry Andric 
21810eae32dcSDimitry Andric   VersionTuple Version = TT.getOSVersion();
21820eae32dcSDimitry Andric   if (!Version.getMajor()) {
2183349cc55cSDimitry Andric     TheDriver.Diag(diag::err_drv_invalid_version_number)
2184349cc55cSDimitry Andric         << A->getAsString(Args);
2185bdd1243dSDimitry Andric     return std::nullopt;
2186349cc55cSDimitry Andric   }
21870eae32dcSDimitry Andric   return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,
2188349cc55cSDimitry Andric                                              TT.getEnvironment(), A, SDKInfo);
2189349cc55cSDimitry Andric }
2190349cc55cSDimitry Andric 
2191bdd1243dSDimitry Andric std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
21920b57cec5SDimitry Andric                                               const ArgList &Args,
21930b57cec5SDimitry Andric                                               const Driver &TheDriver) {
21940b57cec5SDimitry Andric   const Arg *A = Args.getLastArg(options::OPT_isysroot);
21950b57cec5SDimitry Andric   if (!A)
2196bdd1243dSDimitry Andric     return std::nullopt;
21970b57cec5SDimitry Andric   StringRef isysroot = A->getValue();
2198fe6060f1SDimitry Andric   auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
21990b57cec5SDimitry Andric   if (!SDKInfoOrErr) {
22000b57cec5SDimitry Andric     llvm::consumeError(SDKInfoOrErr.takeError());
22010b57cec5SDimitry Andric     TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
2202bdd1243dSDimitry Andric     return std::nullopt;
22030b57cec5SDimitry Andric   }
22040b57cec5SDimitry Andric   return *SDKInfoOrErr;
22050b57cec5SDimitry Andric }
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric } // namespace
22080b57cec5SDimitry Andric 
22090b57cec5SDimitry Andric void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
22100b57cec5SDimitry Andric   const OptTable &Opts = getDriver().getOpts();
22110b57cec5SDimitry Andric 
22120b57cec5SDimitry Andric   // Support allowing the SDKROOT environment variable used by xcrun and other
22130b57cec5SDimitry Andric   // Xcode tools to define the default sysroot, by making it the default for
22140b57cec5SDimitry Andric   // isysroot.
22150b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
22160b57cec5SDimitry Andric     // Warn if the path does not exist.
22170b57cec5SDimitry Andric     if (!getVFS().exists(A->getValue()))
22180b57cec5SDimitry Andric       getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
22190b57cec5SDimitry Andric   } else {
22200b57cec5SDimitry Andric     if (char *env = ::getenv("SDKROOT")) {
22210b57cec5SDimitry Andric       // We only use this value as the default if it is an absolute path,
22220b57cec5SDimitry Andric       // exists, and it is not the root path.
22230b57cec5SDimitry Andric       if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
22240b57cec5SDimitry Andric           StringRef(env) != "/") {
22250b57cec5SDimitry Andric         Args.append(Args.MakeSeparateArg(
22260b57cec5SDimitry Andric             nullptr, Opts.getOption(options::OPT_isysroot), env));
22270b57cec5SDimitry Andric       }
22280b57cec5SDimitry Andric     }
22290b57cec5SDimitry Andric   }
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric   // Read the SDKSettings.json file for more information, like the SDK version
22320b57cec5SDimitry Andric   // that we can pass down to the compiler.
22330b57cec5SDimitry Andric   SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric   // The OS and the version can be specified using the -target argument.
2236bdd1243dSDimitry Andric   std::optional<DarwinPlatform> OSTarget =
2237fe6060f1SDimitry Andric       getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
22380b57cec5SDimitry Andric   if (OSTarget) {
2239349cc55cSDimitry Andric     // Disallow mixing -target and -mtargetos=.
2240349cc55cSDimitry Andric     if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
2241349cc55cSDimitry Andric       std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
2242349cc55cSDimitry Andric       std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
2243349cc55cSDimitry Andric       getDriver().Diag(diag::err_drv_cannot_mix_options)
2244349cc55cSDimitry Andric           << TargetArgStr << MTargetOSArgStr;
2245349cc55cSDimitry Andric     }
2246bdd1243dSDimitry Andric     std::optional<DarwinPlatform> OSVersionArgTarget =
22470b57cec5SDimitry Andric         getDeploymentTargetFromOSVersionArg(Args, getDriver());
22480b57cec5SDimitry Andric     if (OSVersionArgTarget) {
22490b57cec5SDimitry Andric       unsigned TargetMajor, TargetMinor, TargetMicro;
22500b57cec5SDimitry Andric       bool TargetExtra;
22510b57cec5SDimitry Andric       unsigned ArgMajor, ArgMinor, ArgMicro;
22520b57cec5SDimitry Andric       bool ArgExtra;
22530b57cec5SDimitry Andric       if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
22540b57cec5SDimitry Andric           (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
22550b57cec5SDimitry Andric                                      TargetMinor, TargetMicro, TargetExtra) &&
22560b57cec5SDimitry Andric            Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
22570b57cec5SDimitry Andric                                      ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
22580b57cec5SDimitry Andric            (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
22590b57cec5SDimitry Andric                 VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
22600b57cec5SDimitry Andric             TargetExtra != ArgExtra))) {
22610b57cec5SDimitry Andric         // Select the OS version from the -m<os>-version-min argument when
22620b57cec5SDimitry Andric         // the -target does not include an OS version.
22630b57cec5SDimitry Andric         if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
22640b57cec5SDimitry Andric             !OSTarget->hasOSVersion()) {
22650b57cec5SDimitry Andric           OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
22660b57cec5SDimitry Andric         } else {
22670b57cec5SDimitry Andric           // Warn about -m<os>-version-min that doesn't match the OS version
22680b57cec5SDimitry Andric           // that's specified in the target.
22690b57cec5SDimitry Andric           std::string OSVersionArg =
22700b57cec5SDimitry Andric               OSVersionArgTarget->getAsString(Args, Opts);
22710b57cec5SDimitry Andric           std::string TargetArg = OSTarget->getAsString(Args, Opts);
22725f757f3fSDimitry Andric           getDriver().Diag(clang::diag::warn_drv_overriding_option)
22730b57cec5SDimitry Andric               << OSVersionArg << TargetArg;
22740b57cec5SDimitry Andric         }
22750b57cec5SDimitry Andric       }
22760b57cec5SDimitry Andric     }
2277349cc55cSDimitry Andric   } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
2278349cc55cSDimitry Andric                                                              SDKInfo))) {
2279349cc55cSDimitry Andric     // The OS target can be specified using the -mtargetos= argument.
2280349cc55cSDimitry Andric     // Disallow mixing -mtargetos= and -m<os>version-min=.
2281bdd1243dSDimitry Andric     std::optional<DarwinPlatform> OSVersionArgTarget =
2282349cc55cSDimitry Andric         getDeploymentTargetFromOSVersionArg(Args, getDriver());
2283349cc55cSDimitry Andric     if (OSVersionArgTarget) {
2284349cc55cSDimitry Andric       std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
2285349cc55cSDimitry Andric       std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);
2286349cc55cSDimitry Andric       getDriver().Diag(diag::err_drv_cannot_mix_options)
2287349cc55cSDimitry Andric           << MTargetOSArgStr << OSVersionArgStr;
2288349cc55cSDimitry Andric     }
22890b57cec5SDimitry Andric   } else {
22900b57cec5SDimitry Andric     // The OS target can be specified using the -m<os>version-min argument.
22910b57cec5SDimitry Andric     OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
22920b57cec5SDimitry Andric     // If no deployment target was specified on the command line, check for
22930b57cec5SDimitry Andric     // environment defines.
22940b57cec5SDimitry Andric     if (!OSTarget) {
22950b57cec5SDimitry Andric       OSTarget =
22960b57cec5SDimitry Andric           getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
22970b57cec5SDimitry Andric       if (OSTarget) {
22980b57cec5SDimitry Andric         // Don't infer simulator from the arch when the SDK is also specified.
2299bdd1243dSDimitry Andric         std::optional<DarwinPlatform> SDKTarget =
23000b57cec5SDimitry Andric             inferDeploymentTargetFromSDK(Args, SDKInfo);
23010b57cec5SDimitry Andric         if (SDKTarget)
23020b57cec5SDimitry Andric           OSTarget->setEnvironment(SDKTarget->getEnvironment());
23030b57cec5SDimitry Andric       }
23040b57cec5SDimitry Andric     }
23050b57cec5SDimitry Andric     // If there is no command-line argument to specify the Target version and
23060b57cec5SDimitry Andric     // no environment variable defined, see if we can set the default based
23070b57cec5SDimitry Andric     // on -isysroot using SDKSettings.json if it exists.
23080b57cec5SDimitry Andric     if (!OSTarget) {
23090b57cec5SDimitry Andric       OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
23100b57cec5SDimitry Andric       /// If the target was successfully constructed from the SDK path, try to
23110b57cec5SDimitry Andric       /// infer the SDK info if the SDK doesn't have it.
23120b57cec5SDimitry Andric       if (OSTarget && !SDKInfo)
23130b57cec5SDimitry Andric         SDKInfo = OSTarget->inferSDKInfo();
23140b57cec5SDimitry Andric     }
23150b57cec5SDimitry Andric     // If no OS targets have been specified, try to guess platform from -target
23160b57cec5SDimitry Andric     // or arch name and compute the version from the triple.
23170b57cec5SDimitry Andric     if (!OSTarget)
23180b57cec5SDimitry Andric       OSTarget =
23190b57cec5SDimitry Andric           inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
23200b57cec5SDimitry Andric   }
23210b57cec5SDimitry Andric 
23220b57cec5SDimitry Andric   assert(OSTarget && "Unable to infer Darwin variant");
23230b57cec5SDimitry Andric   OSTarget->addOSVersionMinArgument(Args, Opts);
23240b57cec5SDimitry Andric   DarwinPlatformKind Platform = OSTarget->getPlatform();
23250b57cec5SDimitry Andric 
23260b57cec5SDimitry Andric   unsigned Major, Minor, Micro;
23270b57cec5SDimitry Andric   bool HadExtra;
2328bdd1243dSDimitry Andric   // The major version should not be over this number.
2329bdd1243dSDimitry Andric   const unsigned MajorVersionLimit = 1000;
23300b57cec5SDimitry Andric   // Set the tool chain target information.
23310b57cec5SDimitry Andric   if (Platform == MacOS) {
23320b57cec5SDimitry Andric     if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
23330b57cec5SDimitry Andric                                    Micro, HadExtra) ||
2334bdd1243dSDimitry Andric         HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
2335bdd1243dSDimitry Andric         Micro >= 100)
23360b57cec5SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
23370b57cec5SDimitry Andric           << OSTarget->getAsString(Args, Opts);
23380b57cec5SDimitry Andric   } else if (Platform == IPhoneOS) {
23390b57cec5SDimitry Andric     if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
23400b57cec5SDimitry Andric                                    Micro, HadExtra) ||
2341bdd1243dSDimitry Andric         HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
23420b57cec5SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
23430b57cec5SDimitry Andric           << OSTarget->getAsString(Args, Opts);
23440b57cec5SDimitry Andric     ;
2345fe6060f1SDimitry Andric     if (OSTarget->getEnvironment() == MacCatalyst &&
2346fe6060f1SDimitry Andric         (Major < 13 || (Major == 13 && Minor < 1))) {
2347fe6060f1SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
2348fe6060f1SDimitry Andric           << OSTarget->getAsString(Args, Opts);
2349fe6060f1SDimitry Andric       Major = 13;
2350fe6060f1SDimitry Andric       Minor = 1;
2351fe6060f1SDimitry Andric       Micro = 0;
2352fe6060f1SDimitry Andric     }
23530b57cec5SDimitry Andric     // For 32-bit targets, the deployment target for iOS has to be earlier than
23540b57cec5SDimitry Andric     // iOS 11.
23550b57cec5SDimitry Andric     if (getTriple().isArch32Bit() && Major >= 11) {
23560b57cec5SDimitry Andric       // If the deployment target is explicitly specified, print a diagnostic.
23570b57cec5SDimitry Andric       if (OSTarget->isExplicitlySpecified()) {
2358fe6060f1SDimitry Andric         if (OSTarget->getEnvironment() == MacCatalyst)
2359fe6060f1SDimitry Andric           getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
2360fe6060f1SDimitry Andric         else
23610b57cec5SDimitry Andric           getDriver().Diag(diag::warn_invalid_ios_deployment_target)
23620b57cec5SDimitry Andric               << OSTarget->getAsString(Args, Opts);
23630b57cec5SDimitry Andric         // Otherwise, set it to 10.99.99.
23640b57cec5SDimitry Andric       } else {
23650b57cec5SDimitry Andric         Major = 10;
23660b57cec5SDimitry Andric         Minor = 99;
23670b57cec5SDimitry Andric         Micro = 99;
23680b57cec5SDimitry Andric       }
23690b57cec5SDimitry Andric     }
23700b57cec5SDimitry Andric   } else if (Platform == TvOS) {
23710b57cec5SDimitry Andric     if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
23720b57cec5SDimitry Andric                                    Micro, HadExtra) ||
2373bdd1243dSDimitry Andric         HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
23740b57cec5SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
23750b57cec5SDimitry Andric           << OSTarget->getAsString(Args, Opts);
23760b57cec5SDimitry Andric   } else if (Platform == WatchOS) {
23770b57cec5SDimitry Andric     if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
23780b57cec5SDimitry Andric                                    Micro, HadExtra) ||
2379bdd1243dSDimitry Andric         HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
23800b57cec5SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
23810b57cec5SDimitry Andric           << OSTarget->getAsString(Args, Opts);
238281ad6265SDimitry Andric   } else if (Platform == DriverKit) {
238381ad6265SDimitry Andric     if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
238481ad6265SDimitry Andric                                    Micro, HadExtra) ||
2385bdd1243dSDimitry Andric         HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
2386bdd1243dSDimitry Andric         Micro >= 100)
238781ad6265SDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
238881ad6265SDimitry Andric           << OSTarget->getAsString(Args, Opts);
23897a6dacacSDimitry Andric   } else if (Platform == XROS) {
23907a6dacacSDimitry Andric     if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
23917a6dacacSDimitry Andric                                    Micro, HadExtra) ||
23927a6dacacSDimitry Andric         HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
23937a6dacacSDimitry Andric         Micro >= 100)
23947a6dacacSDimitry Andric       getDriver().Diag(diag::err_drv_invalid_version_number)
23957a6dacacSDimitry Andric           << OSTarget->getAsString(Args, Opts);
23960b57cec5SDimitry Andric   } else
23970b57cec5SDimitry Andric     llvm_unreachable("unknown kind of Darwin platform");
23980b57cec5SDimitry Andric 
23990b57cec5SDimitry Andric   DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
24000b57cec5SDimitry Andric   // Recognize iOS targets with an x86 architecture as the iOS simulator.
24010b57cec5SDimitry Andric   if (Environment == NativeEnvironment && Platform != MacOS &&
240281ad6265SDimitry Andric       Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
240381ad6265SDimitry Andric       getTriple().isX86())
24040b57cec5SDimitry Andric     Environment = Simulator;
24050b57cec5SDimitry Andric 
2406fe6060f1SDimitry Andric   VersionTuple NativeTargetVersion;
2407fe6060f1SDimitry Andric   if (Environment == MacCatalyst)
2408fe6060f1SDimitry Andric     NativeTargetVersion = OSTarget->getNativeTargetVersion();
2409fe6060f1SDimitry Andric   setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
241081ad6265SDimitry Andric   TargetVariantTriple = OSTarget->getTargetVariantTriple();
24110b57cec5SDimitry Andric 
24120b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
24130b57cec5SDimitry Andric     StringRef SDK = getSDKName(A->getValue());
24140b57cec5SDimitry Andric     if (SDK.size() > 0) {
24150b57cec5SDimitry Andric       size_t StartVer = SDK.find_first_of("0123456789");
24160b57cec5SDimitry Andric       StringRef SDKName = SDK.slice(0, StartVer);
24175f757f3fSDimitry Andric       if (!SDKName.starts_with(getPlatformFamily()) &&
24185f757f3fSDimitry Andric           !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))
24190b57cec5SDimitry Andric         getDriver().Diag(diag::warn_incompatible_sysroot)
24200b57cec5SDimitry Andric             << SDKName << getPlatformFamily();
24210b57cec5SDimitry Andric     }
24220b57cec5SDimitry Andric   }
24230b57cec5SDimitry Andric }
24240b57cec5SDimitry Andric 
2425bdd1243dSDimitry Andric // For certain platforms/environments almost all resources (e.g., headers) are
2426bdd1243dSDimitry Andric // located in sub-directories, e.g., for DriverKit they live in
2427bdd1243dSDimitry Andric // <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).
2428bdd1243dSDimitry Andric static void AppendPlatformPrefix(SmallString<128> &Path,
2429bdd1243dSDimitry Andric                                  const llvm::Triple &T) {
2430bdd1243dSDimitry Andric   if (T.isDriverKit()) {
2431bdd1243dSDimitry Andric     llvm::sys::path::append(Path, "System", "DriverKit");
2432bdd1243dSDimitry Andric   }
2433bdd1243dSDimitry Andric }
2434bdd1243dSDimitry Andric 
2435bdd1243dSDimitry Andric // Returns the effective sysroot from either -isysroot or --sysroot, plus the
2436bdd1243dSDimitry Andric // platform prefix (if any).
2437bdd1243dSDimitry Andric llvm::SmallString<128>
2438bdd1243dSDimitry Andric DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2439bdd1243dSDimitry Andric   llvm::SmallString<128> Path("/");
24400b57cec5SDimitry Andric   if (DriverArgs.hasArg(options::OPT_isysroot))
2441bdd1243dSDimitry Andric     Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
2442bdd1243dSDimitry Andric   else if (!getDriver().SysRoot.empty())
2443bdd1243dSDimitry Andric     Path = getDriver().SysRoot;
2444bdd1243dSDimitry Andric 
2445bdd1243dSDimitry Andric   if (hasEffectiveTriple()) {
2446bdd1243dSDimitry Andric     AppendPlatformPrefix(Path, getEffectiveTriple());
2447bdd1243dSDimitry Andric   }
2448bdd1243dSDimitry Andric   return Path;
24490b57cec5SDimitry Andric }
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
24520b57cec5SDimitry Andric                                             llvm::opt::ArgStringList &CC1Args) const {
24530b57cec5SDimitry Andric   const Driver &D = getDriver();
24540b57cec5SDimitry Andric 
2455bdd1243dSDimitry Andric   llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric   bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
24580b57cec5SDimitry Andric   bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
24595ffd83dbSDimitry Andric   bool NoBuiltinInc = DriverArgs.hasFlag(
24605ffd83dbSDimitry Andric       options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
24615ffd83dbSDimitry Andric   bool ForceBuiltinInc = DriverArgs.hasFlag(
24625ffd83dbSDimitry Andric       options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric   // Add <sysroot>/usr/local/include
24650b57cec5SDimitry Andric   if (!NoStdInc && !NoStdlibInc) {
24660b57cec5SDimitry Andric       SmallString<128> P(Sysroot);
24670b57cec5SDimitry Andric       llvm::sys::path::append(P, "usr", "local", "include");
24680b57cec5SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, P);
24690b57cec5SDimitry Andric   }
24700b57cec5SDimitry Andric 
24710b57cec5SDimitry Andric   // Add the Clang builtin headers (<resource>/include)
24725ffd83dbSDimitry Andric   if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
24730b57cec5SDimitry Andric     SmallString<128> P(D.ResourceDir);
24740b57cec5SDimitry Andric     llvm::sys::path::append(P, "include");
24750b57cec5SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, P);
24760b57cec5SDimitry Andric   }
24770b57cec5SDimitry Andric 
24780b57cec5SDimitry Andric   if (NoStdInc || NoStdlibInc)
24790b57cec5SDimitry Andric     return;
24800b57cec5SDimitry Andric 
24810b57cec5SDimitry Andric   // Check for configure-time C include directories.
24820b57cec5SDimitry Andric   llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
24830b57cec5SDimitry Andric   if (!CIncludeDirs.empty()) {
24840b57cec5SDimitry Andric     llvm::SmallVector<llvm::StringRef, 5> dirs;
24850b57cec5SDimitry Andric     CIncludeDirs.split(dirs, ":");
24860b57cec5SDimitry Andric     for (llvm::StringRef dir : dirs) {
24870b57cec5SDimitry Andric       llvm::StringRef Prefix =
24885ffd83dbSDimitry Andric           llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
24890b57cec5SDimitry Andric       addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
24900b57cec5SDimitry Andric     }
24910b57cec5SDimitry Andric   } else {
24920b57cec5SDimitry Andric     // Otherwise, add <sysroot>/usr/include.
24930b57cec5SDimitry Andric     SmallString<128> P(Sysroot);
24940b57cec5SDimitry Andric     llvm::sys::path::append(P, "usr", "include");
24950b57cec5SDimitry Andric     addExternCSystemInclude(DriverArgs, CC1Args, P.str());
24960b57cec5SDimitry Andric   }
24970b57cec5SDimitry Andric }
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
25000b57cec5SDimitry Andric                                               llvm::opt::ArgStringList &CC1Args,
25010b57cec5SDimitry Andric                                               llvm::SmallString<128> Base,
25020b57cec5SDimitry Andric                                               llvm::StringRef Version,
25030b57cec5SDimitry Andric                                               llvm::StringRef ArchDir,
25040b57cec5SDimitry Andric                                               llvm::StringRef BitDir) const {
25050b57cec5SDimitry Andric   llvm::sys::path::append(Base, Version);
25060b57cec5SDimitry Andric 
25070b57cec5SDimitry Andric   // Add the base dir
25080b57cec5SDimitry Andric   addSystemInclude(DriverArgs, CC1Args, Base);
25090b57cec5SDimitry Andric 
25100b57cec5SDimitry Andric   // Add the multilib dirs
25110b57cec5SDimitry Andric   {
25120b57cec5SDimitry Andric     llvm::SmallString<128> P = Base;
25130b57cec5SDimitry Andric     if (!ArchDir.empty())
25140b57cec5SDimitry Andric       llvm::sys::path::append(P, ArchDir);
25150b57cec5SDimitry Andric     if (!BitDir.empty())
25160b57cec5SDimitry Andric       llvm::sys::path::append(P, BitDir);
25170b57cec5SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, P);
25180b57cec5SDimitry Andric   }
25190b57cec5SDimitry Andric 
25200b57cec5SDimitry Andric   // Add the backward dir
25210b57cec5SDimitry Andric   {
25220b57cec5SDimitry Andric     llvm::SmallString<128> P = Base;
25230b57cec5SDimitry Andric     llvm::sys::path::append(P, "backward");
25240b57cec5SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, P);
25250b57cec5SDimitry Andric   }
25260b57cec5SDimitry Andric 
25270b57cec5SDimitry Andric   return getVFS().exists(Base);
25280b57cec5SDimitry Andric }
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric void DarwinClang::AddClangCXXStdlibIncludeArgs(
25310b57cec5SDimitry Andric     const llvm::opt::ArgList &DriverArgs,
25320b57cec5SDimitry Andric     llvm::opt::ArgStringList &CC1Args) const {
25330b57cec5SDimitry Andric   // The implementation from a base class will pass through the -stdlib to
25340b57cec5SDimitry Andric   // CC1Args.
25350b57cec5SDimitry Andric   // FIXME: this should not be necessary, remove usages in the frontend
25360b57cec5SDimitry Andric   //        (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
25370b57cec5SDimitry Andric   //        Also check whether this is used for setting library search paths.
25380b57cec5SDimitry Andric   ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
25390b57cec5SDimitry Andric 
2540bdd1243dSDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
2541bdd1243dSDimitry Andric                         options::OPT_nostdincxx))
25420b57cec5SDimitry Andric     return;
25430b57cec5SDimitry Andric 
2544bdd1243dSDimitry Andric   llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
25450b57cec5SDimitry Andric 
25460b57cec5SDimitry Andric   switch (GetCXXStdlibType(DriverArgs)) {
25470b57cec5SDimitry Andric   case ToolChain::CST_Libcxx: {
25485f757f3fSDimitry Andric     // On Darwin, libc++ can be installed in one of the following places:
25490fca6ea1SDimitry Andric     // 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
25500fca6ea1SDimitry Andric     // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
2551e8d8bef9SDimitry Andric     //
25525f757f3fSDimitry Andric     // The precedence of paths is as listed above, i.e. we take the first path
25535f757f3fSDimitry Andric     // that exists. Note that we never include libc++ twice -- we take the first
25545f757f3fSDimitry Andric     // path that exists and don't send the other paths to CC1 (otherwise
2555e8d8bef9SDimitry Andric     // include_next could break).
2556e8d8bef9SDimitry Andric 
2557e8d8bef9SDimitry Andric     // Check for (1)
2558e8d8bef9SDimitry Andric     // Get from '<install>/bin' to '<install>/include/c++/v1'.
2559e8d8bef9SDimitry Andric     // Note that InstallBin can be relative, so we use '..' instead of
2560e8d8bef9SDimitry Andric     // parent_path.
25610fca6ea1SDimitry Andric     llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin
2562e8d8bef9SDimitry Andric     llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
2563e8d8bef9SDimitry Andric     if (getVFS().exists(InstallBin)) {
2564e8d8bef9SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, InstallBin);
2565e8d8bef9SDimitry Andric       return;
2566e8d8bef9SDimitry Andric     } else if (DriverArgs.hasArg(options::OPT_v)) {
2567e8d8bef9SDimitry Andric       llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
2568e8d8bef9SDimitry Andric                    << "\"\n";
25690b57cec5SDimitry Andric     }
2570e8d8bef9SDimitry Andric 
25710fca6ea1SDimitry Andric     // Otherwise, check for (2)
2572e8d8bef9SDimitry Andric     llvm::SmallString<128> SysrootUsr = Sysroot;
2573e8d8bef9SDimitry Andric     llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
2574e8d8bef9SDimitry Andric     if (getVFS().exists(SysrootUsr)) {
2575e8d8bef9SDimitry Andric       addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
2576e8d8bef9SDimitry Andric       return;
2577e8d8bef9SDimitry Andric     } else if (DriverArgs.hasArg(options::OPT_v)) {
2578e8d8bef9SDimitry Andric       llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
2579e8d8bef9SDimitry Andric                    << "\"\n";
25800b57cec5SDimitry Andric     }
2581e8d8bef9SDimitry Andric 
2582e8d8bef9SDimitry Andric     // Otherwise, don't add any path.
25830b57cec5SDimitry Andric     break;
25840b57cec5SDimitry Andric   }
25850b57cec5SDimitry Andric 
25860b57cec5SDimitry Andric   case ToolChain::CST_Libstdcxx:
25870b57cec5SDimitry Andric     llvm::SmallString<128> UsrIncludeCxx = Sysroot;
25880b57cec5SDimitry Andric     llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
25890b57cec5SDimitry Andric 
25900b57cec5SDimitry Andric     llvm::Triple::ArchType arch = getTriple().getArch();
25910b57cec5SDimitry Andric     bool IsBaseFound = true;
25920b57cec5SDimitry Andric     switch (arch) {
25930b57cec5SDimitry Andric     default: break;
25940b57cec5SDimitry Andric 
25950b57cec5SDimitry Andric     case llvm::Triple::x86:
25960b57cec5SDimitry Andric     case llvm::Triple::x86_64:
25970b57cec5SDimitry Andric       IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
25980b57cec5SDimitry Andric                                                 "4.2.1",
25990b57cec5SDimitry Andric                                                 "i686-apple-darwin10",
26000b57cec5SDimitry Andric                                                 arch == llvm::Triple::x86_64 ? "x86_64" : "");
26010b57cec5SDimitry Andric       IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
26020b57cec5SDimitry Andric                                                 "4.0.0", "i686-apple-darwin8",
26030b57cec5SDimitry Andric                                                  "");
26040b57cec5SDimitry Andric       break;
26050b57cec5SDimitry Andric 
26060b57cec5SDimitry Andric     case llvm::Triple::arm:
26070b57cec5SDimitry Andric     case llvm::Triple::thumb:
26080b57cec5SDimitry Andric       IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
26090b57cec5SDimitry Andric                                                 "4.2.1",
26100b57cec5SDimitry Andric                                                 "arm-apple-darwin10",
26110b57cec5SDimitry Andric                                                 "v7");
26120b57cec5SDimitry Andric       IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
26130b57cec5SDimitry Andric                                                 "4.2.1",
26140b57cec5SDimitry Andric                                                 "arm-apple-darwin10",
26150b57cec5SDimitry Andric                                                  "v6");
26160b57cec5SDimitry Andric       break;
26170b57cec5SDimitry Andric 
26180b57cec5SDimitry Andric     case llvm::Triple::aarch64:
26190b57cec5SDimitry Andric       IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
26200b57cec5SDimitry Andric                                                 "4.2.1",
26210b57cec5SDimitry Andric                                                 "arm64-apple-darwin10",
26220b57cec5SDimitry Andric                                                 "");
26230b57cec5SDimitry Andric       break;
26240b57cec5SDimitry Andric     }
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric     if (!IsBaseFound) {
26270b57cec5SDimitry Andric       getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
26280b57cec5SDimitry Andric     }
26290b57cec5SDimitry Andric 
26300b57cec5SDimitry Andric     break;
26310b57cec5SDimitry Andric   }
26320b57cec5SDimitry Andric }
2633fcaf7f86SDimitry Andric 
26340b57cec5SDimitry Andric void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
26350b57cec5SDimitry Andric                                       ArgStringList &CmdArgs) const {
26360b57cec5SDimitry Andric   CXXStdlibType Type = GetCXXStdlibType(Args);
26370b57cec5SDimitry Andric 
26380b57cec5SDimitry Andric   switch (Type) {
26390b57cec5SDimitry Andric   case ToolChain::CST_Libcxx:
26400b57cec5SDimitry Andric     CmdArgs.push_back("-lc++");
2641fcaf7f86SDimitry Andric     if (Args.hasArg(options::OPT_fexperimental_library))
2642fcaf7f86SDimitry Andric       CmdArgs.push_back("-lc++experimental");
26430b57cec5SDimitry Andric     break;
26440b57cec5SDimitry Andric 
26450b57cec5SDimitry Andric   case ToolChain::CST_Libstdcxx:
26460b57cec5SDimitry Andric     // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
26470b57cec5SDimitry Andric     // it was previously found in the gcc lib dir. However, for all the Darwin
26480b57cec5SDimitry Andric     // platforms we care about it was -lstdc++.6, so we search for that
26490b57cec5SDimitry Andric     // explicitly if we can't see an obvious -lstdc++ candidate.
26500b57cec5SDimitry Andric 
26510b57cec5SDimitry Andric     // Check in the sysroot first.
26520b57cec5SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
26530b57cec5SDimitry Andric       SmallString<128> P(A->getValue());
26540b57cec5SDimitry Andric       llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
26550b57cec5SDimitry Andric 
26560b57cec5SDimitry Andric       if (!getVFS().exists(P)) {
26570b57cec5SDimitry Andric         llvm::sys::path::remove_filename(P);
26580b57cec5SDimitry Andric         llvm::sys::path::append(P, "libstdc++.6.dylib");
26590b57cec5SDimitry Andric         if (getVFS().exists(P)) {
26600b57cec5SDimitry Andric           CmdArgs.push_back(Args.MakeArgString(P));
26610b57cec5SDimitry Andric           return;
26620b57cec5SDimitry Andric         }
26630b57cec5SDimitry Andric       }
26640b57cec5SDimitry Andric     }
26650b57cec5SDimitry Andric 
26660b57cec5SDimitry Andric     // Otherwise, look in the root.
26670b57cec5SDimitry Andric     // FIXME: This should be removed someday when we don't have to care about
26680b57cec5SDimitry Andric     // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
26690b57cec5SDimitry Andric     if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
26700b57cec5SDimitry Andric         getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
26710b57cec5SDimitry Andric       CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
26720b57cec5SDimitry Andric       return;
26730b57cec5SDimitry Andric     }
26740b57cec5SDimitry Andric 
26750b57cec5SDimitry Andric     // Otherwise, let the linker search.
26760b57cec5SDimitry Andric     CmdArgs.push_back("-lstdc++");
26770b57cec5SDimitry Andric     break;
26780b57cec5SDimitry Andric   }
26790b57cec5SDimitry Andric }
26800b57cec5SDimitry Andric 
26810b57cec5SDimitry Andric void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
26820b57cec5SDimitry Andric                                    ArgStringList &CmdArgs) const {
26830b57cec5SDimitry Andric   // For Darwin platforms, use the compiler-rt-based support library
26840b57cec5SDimitry Andric   // instead of the gcc-provided one (which is also incidentally
26850b57cec5SDimitry Andric   // only present in the gcc lib dir, which makes it hard to find).
26860b57cec5SDimitry Andric 
26870b57cec5SDimitry Andric   SmallString<128> P(getDriver().ResourceDir);
26880b57cec5SDimitry Andric   llvm::sys::path::append(P, "lib", "darwin");
26890b57cec5SDimitry Andric 
26900b57cec5SDimitry Andric   // Use the newer cc_kext for iOS ARM after 6.0.
26910b57cec5SDimitry Andric   if (isTargetWatchOS()) {
26920b57cec5SDimitry Andric     llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
26930b57cec5SDimitry Andric   } else if (isTargetTvOS()) {
26940b57cec5SDimitry Andric     llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
26950b57cec5SDimitry Andric   } else if (isTargetIPhoneOS()) {
26960b57cec5SDimitry Andric     llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
269781ad6265SDimitry Andric   } else if (isTargetDriverKit()) {
269881ad6265SDimitry Andric     // DriverKit doesn't want extra runtime support.
26997a6dacacSDimitry Andric   } else if (isTargetXROSDevice()) {
27007a6dacacSDimitry Andric     llvm::sys::path::append(
27017a6dacacSDimitry Andric         P, llvm::Twine("libclang_rt.cc_kext_") +
27027a6dacacSDimitry Andric                llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a");
27030b57cec5SDimitry Andric   } else {
27040b57cec5SDimitry Andric     llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
27050b57cec5SDimitry Andric   }
27060b57cec5SDimitry Andric 
27070b57cec5SDimitry Andric   // For now, allow missing resource libraries to support developers who may
27080b57cec5SDimitry Andric   // not have compiler-rt checked out or integrated into their build.
27090b57cec5SDimitry Andric   if (getVFS().exists(P))
27100b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(P));
27110b57cec5SDimitry Andric }
27120b57cec5SDimitry Andric 
27130b57cec5SDimitry Andric DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
27140b57cec5SDimitry Andric                                      StringRef BoundArch,
27150b57cec5SDimitry Andric                                      Action::OffloadKind) const {
27160b57cec5SDimitry Andric   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
27170b57cec5SDimitry Andric   const OptTable &Opts = getDriver().getOpts();
27180b57cec5SDimitry Andric 
27190b57cec5SDimitry Andric   // FIXME: We really want to get out of the tool chain level argument
27200b57cec5SDimitry Andric   // translation business, as it makes the driver functionality much
27210b57cec5SDimitry Andric   // more opaque. For now, we follow gcc closely solely for the
27220b57cec5SDimitry Andric   // purpose of easily achieving feature parity & testability. Once we
27230b57cec5SDimitry Andric   // have something that works, we should reevaluate each translation
27240b57cec5SDimitry Andric   // and try to push it down into tool specific logic.
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric   for (Arg *A : Args) {
27270b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_Xarch__)) {
27280b57cec5SDimitry Andric       // Skip this argument unless the architecture matches either the toolchain
27290b57cec5SDimitry Andric       // triple arch, or the arch being bound.
273081ad6265SDimitry Andric       StringRef XarchArch = A->getValue(0);
273181ad6265SDimitry Andric       if (!(XarchArch == getArchName() ||
273281ad6265SDimitry Andric             (!BoundArch.empty() && XarchArch == BoundArch)))
27330b57cec5SDimitry Andric         continue;
27340b57cec5SDimitry Andric 
27350b57cec5SDimitry Andric       Arg *OriginalArg = A;
27365ffd83dbSDimitry Andric       TranslateXarchArgs(Args, A, DAL);
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric       // Linker input arguments require custom handling. The problem is that we
27390b57cec5SDimitry Andric       // have already constructed the phase actions, so we can not treat them as
27400b57cec5SDimitry Andric       // "input arguments".
27410b57cec5SDimitry Andric       if (A->getOption().hasFlag(options::LinkerInput)) {
27420b57cec5SDimitry Andric         // Convert the argument into individual Zlinker_input_args.
27430b57cec5SDimitry Andric         for (const char *Value : A->getValues()) {
27440b57cec5SDimitry Andric           DAL->AddSeparateArg(
27450b57cec5SDimitry Andric               OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
27460b57cec5SDimitry Andric         }
27470b57cec5SDimitry Andric         continue;
27480b57cec5SDimitry Andric       }
27490b57cec5SDimitry Andric     }
27500b57cec5SDimitry Andric 
27510b57cec5SDimitry Andric     // Sob. These is strictly gcc compatible for the time being. Apple
27520b57cec5SDimitry Andric     // gcc translates options twice, which means that self-expanding
27530b57cec5SDimitry Andric     // options add duplicates.
27540b57cec5SDimitry Andric     switch ((options::ID)A->getOption().getID()) {
27550b57cec5SDimitry Andric     default:
27560b57cec5SDimitry Andric       DAL->append(A);
27570b57cec5SDimitry Andric       break;
27580b57cec5SDimitry Andric 
27590b57cec5SDimitry Andric     case options::OPT_mkernel:
27600b57cec5SDimitry Andric     case options::OPT_fapple_kext:
27610b57cec5SDimitry Andric       DAL->append(A);
27620b57cec5SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
27630b57cec5SDimitry Andric       break;
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric     case options::OPT_dependency_file:
27660b57cec5SDimitry Andric       DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
27670b57cec5SDimitry Andric       break;
27680b57cec5SDimitry Andric 
27690b57cec5SDimitry Andric     case options::OPT_gfull:
27700b57cec5SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
27710b57cec5SDimitry Andric       DAL->AddFlagArg(
27720b57cec5SDimitry Andric           A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
27730b57cec5SDimitry Andric       break;
27740b57cec5SDimitry Andric 
27750b57cec5SDimitry Andric     case options::OPT_gused:
27760b57cec5SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
27770b57cec5SDimitry Andric       DAL->AddFlagArg(
27780b57cec5SDimitry Andric           A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
27790b57cec5SDimitry Andric       break;
27800b57cec5SDimitry Andric 
27810b57cec5SDimitry Andric     case options::OPT_shared:
27820b57cec5SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
27830b57cec5SDimitry Andric       break;
27840b57cec5SDimitry Andric 
27850b57cec5SDimitry Andric     case options::OPT_fconstant_cfstrings:
27860b57cec5SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
27870b57cec5SDimitry Andric       break;
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric     case options::OPT_fno_constant_cfstrings:
27900b57cec5SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
27910b57cec5SDimitry Andric       break;
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric     case options::OPT_Wnonportable_cfstrings:
27940b57cec5SDimitry Andric       DAL->AddFlagArg(A,
27950b57cec5SDimitry Andric                       Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
27960b57cec5SDimitry Andric       break;
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric     case options::OPT_Wno_nonportable_cfstrings:
27990b57cec5SDimitry Andric       DAL->AddFlagArg(
28000b57cec5SDimitry Andric           A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
28010b57cec5SDimitry Andric       break;
28020b57cec5SDimitry Andric     }
28030b57cec5SDimitry Andric   }
28040b57cec5SDimitry Andric 
28050b57cec5SDimitry Andric   // Add the arch options based on the particular spelling of -arch, to match
2806bdd1243dSDimitry Andric   // how the driver works.
28070b57cec5SDimitry Andric   if (!BoundArch.empty()) {
28080b57cec5SDimitry Andric     StringRef Name = BoundArch;
28090b57cec5SDimitry Andric     const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
28100b57cec5SDimitry Andric     const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);
28110b57cec5SDimitry Andric 
28120b57cec5SDimitry Andric     // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
28130b57cec5SDimitry Andric     // which defines the list of which architectures we accept.
28140b57cec5SDimitry Andric     if (Name == "ppc")
28150b57cec5SDimitry Andric       ;
28160b57cec5SDimitry Andric     else if (Name == "ppc601")
28170b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "601");
28180b57cec5SDimitry Andric     else if (Name == "ppc603")
28190b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "603");
28200b57cec5SDimitry Andric     else if (Name == "ppc604")
28210b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "604");
28220b57cec5SDimitry Andric     else if (Name == "ppc604e")
28230b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "604e");
28240b57cec5SDimitry Andric     else if (Name == "ppc750")
28250b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "750");
28260b57cec5SDimitry Andric     else if (Name == "ppc7400")
28270b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "7400");
28280b57cec5SDimitry Andric     else if (Name == "ppc7450")
28290b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "7450");
28300b57cec5SDimitry Andric     else if (Name == "ppc970")
28310b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MCpu, "970");
28320b57cec5SDimitry Andric 
28330b57cec5SDimitry Andric     else if (Name == "ppc64" || Name == "ppc64le")
28340b57cec5SDimitry Andric       DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
28350b57cec5SDimitry Andric 
28360b57cec5SDimitry Andric     else if (Name == "i386")
28370b57cec5SDimitry Andric       ;
28380b57cec5SDimitry Andric     else if (Name == "i486")
28390b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "i486");
28400b57cec5SDimitry Andric     else if (Name == "i586")
28410b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "i586");
28420b57cec5SDimitry Andric     else if (Name == "i686")
28430b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "i686");
28440b57cec5SDimitry Andric     else if (Name == "pentium")
28450b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "pentium");
28460b57cec5SDimitry Andric     else if (Name == "pentium2")
28470b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "pentium2");
28480b57cec5SDimitry Andric     else if (Name == "pentpro")
28490b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
28500b57cec5SDimitry Andric     else if (Name == "pentIIm3")
28510b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "pentium2");
28520b57cec5SDimitry Andric 
28530b57cec5SDimitry Andric     else if (Name == "x86_64" || Name == "x86_64h")
28540b57cec5SDimitry Andric       DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
28550b57cec5SDimitry Andric 
28560b57cec5SDimitry Andric     else if (Name == "arm")
28570b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv4t");
28580b57cec5SDimitry Andric     else if (Name == "armv4t")
28590b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv4t");
28600b57cec5SDimitry Andric     else if (Name == "armv5")
28610b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
28620b57cec5SDimitry Andric     else if (Name == "xscale")
28630b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "xscale");
28640b57cec5SDimitry Andric     else if (Name == "armv6")
28650b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv6k");
28660b57cec5SDimitry Andric     else if (Name == "armv6m")
28670b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv6m");
28680b57cec5SDimitry Andric     else if (Name == "armv7")
28690b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv7a");
28700b57cec5SDimitry Andric     else if (Name == "armv7em")
28710b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv7em");
28720b57cec5SDimitry Andric     else if (Name == "armv7k")
28730b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv7k");
28740b57cec5SDimitry Andric     else if (Name == "armv7m")
28750b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv7m");
28760b57cec5SDimitry Andric     else if (Name == "armv7s")
28770b57cec5SDimitry Andric       DAL->AddJoinedArg(nullptr, MArch, "armv7s");
28780b57cec5SDimitry Andric   }
28790b57cec5SDimitry Andric 
28800b57cec5SDimitry Andric   return DAL;
28810b57cec5SDimitry Andric }
28820b57cec5SDimitry Andric 
28830b57cec5SDimitry Andric void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
28840b57cec5SDimitry Andric                                   ArgStringList &CmdArgs,
28850b57cec5SDimitry Andric                                   bool ForceLinkBuiltinRT) const {
28860b57cec5SDimitry Andric   // Embedded targets are simple at the moment, not supporting sanitizers and
28870b57cec5SDimitry Andric   // with different libraries for each member of the product { static, PIC } x
28880b57cec5SDimitry Andric   // { hard-float, soft-float }
28890b57cec5SDimitry Andric   llvm::SmallString<32> CompilerRT = StringRef("");
28900b57cec5SDimitry Andric   CompilerRT +=
28910b57cec5SDimitry Andric       (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
28920b57cec5SDimitry Andric           ? "hard"
28930b57cec5SDimitry Andric           : "soft";
28940b57cec5SDimitry Andric   CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
28950b57cec5SDimitry Andric 
28960b57cec5SDimitry Andric   AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
28970b57cec5SDimitry Andric }
28980b57cec5SDimitry Andric 
28990b57cec5SDimitry Andric bool Darwin::isAlignedAllocationUnavailable() const {
29000b57cec5SDimitry Andric   llvm::Triple::OSType OS;
29010b57cec5SDimitry Andric 
2902fe6060f1SDimitry Andric   if (isTargetMacCatalyst())
2903fe6060f1SDimitry Andric     return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);
29040b57cec5SDimitry Andric   switch (TargetPlatform) {
29050b57cec5SDimitry Andric   case MacOS: // Earlier than 10.13.
29060b57cec5SDimitry Andric     OS = llvm::Triple::MacOSX;
29070b57cec5SDimitry Andric     break;
29080b57cec5SDimitry Andric   case IPhoneOS:
29090b57cec5SDimitry Andric     OS = llvm::Triple::IOS;
29100b57cec5SDimitry Andric     break;
29110b57cec5SDimitry Andric   case TvOS: // Earlier than 11.0.
29120b57cec5SDimitry Andric     OS = llvm::Triple::TvOS;
29130b57cec5SDimitry Andric     break;
29140b57cec5SDimitry Andric   case WatchOS: // Earlier than 4.0.
29150b57cec5SDimitry Andric     OS = llvm::Triple::WatchOS;
29160b57cec5SDimitry Andric     break;
29177a6dacacSDimitry Andric   case XROS: // Always available.
29187a6dacacSDimitry Andric     return false;
291981ad6265SDimitry Andric   case DriverKit: // Always available.
292081ad6265SDimitry Andric     return false;
29210b57cec5SDimitry Andric   }
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric   return TargetVersion < alignedAllocMinVersion(OS);
29240b57cec5SDimitry Andric }
29250b57cec5SDimitry Andric 
292662987288SDimitry Andric static bool sdkSupportsBuiltinModules(
292762987288SDimitry Andric     const Darwin::DarwinPlatformKind &TargetPlatform,
292862987288SDimitry Andric     const Darwin::DarwinEnvironmentKind &TargetEnvironment,
292962987288SDimitry Andric     const std::optional<DarwinSDKInfo> &SDKInfo) {
293062987288SDimitry Andric   if (TargetEnvironment == Darwin::NativeEnvironment ||
293162987288SDimitry Andric       TargetEnvironment == Darwin::Simulator ||
293262987288SDimitry Andric       TargetEnvironment == Darwin::MacCatalyst) {
293362987288SDimitry Andric     // Standard xnu/Mach/Darwin based environments
293462987288SDimitry Andric     // depend on the SDK version.
293562987288SDimitry Andric   } else {
293662987288SDimitry Andric     // All other environments support builtin modules from the start.
293762987288SDimitry Andric     return true;
293862987288SDimitry Andric   }
293962987288SDimitry Andric 
29405f757f3fSDimitry Andric   if (!SDKInfo)
294162987288SDimitry Andric     // If there is no SDK info, assume this is building against a
294262987288SDimitry Andric     // pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those
294362987288SDimitry Andric     // don't support modules anyway, but the headers definitely
294462987288SDimitry Andric     // don't support builtin modules either. It might also be some
294562987288SDimitry Andric     // kind of degenerate build environment, err on the side of
294662987288SDimitry Andric     // the old behavior which is to not use builtin modules.
29475f757f3fSDimitry Andric     return false;
29485f757f3fSDimitry Andric 
29495f757f3fSDimitry Andric   VersionTuple SDKVersion = SDKInfo->getVersion();
29505f757f3fSDimitry Andric   switch (TargetPlatform) {
295162987288SDimitry Andric   // Existing SDKs added support for builtin modules in the fall
295262987288SDimitry Andric   // 2024 major releases.
29535f757f3fSDimitry Andric   case Darwin::MacOS:
295462987288SDimitry Andric     return SDKVersion >= VersionTuple(15U);
29555f757f3fSDimitry Andric   case Darwin::IPhoneOS:
2956*6c4b055cSDimitry Andric     switch (TargetEnvironment) {
2957*6c4b055cSDimitry Andric     case Darwin::MacCatalyst:
2958*6c4b055cSDimitry Andric       // Mac Catalyst uses `-target arm64-apple-ios18.0-macabi` so the platform
2959*6c4b055cSDimitry Andric       // is iOS, but it builds with the macOS SDK, so it's the macOS SDK version
2960*6c4b055cSDimitry Andric       // that's relevant.
2961*6c4b055cSDimitry Andric       return SDKVersion >= VersionTuple(15U);
2962*6c4b055cSDimitry Andric     default:
296362987288SDimitry Andric       return SDKVersion >= VersionTuple(18U);
2964*6c4b055cSDimitry Andric     }
29655f757f3fSDimitry Andric   case Darwin::TvOS:
296662987288SDimitry Andric     return SDKVersion >= VersionTuple(18U);
29675f757f3fSDimitry Andric   case Darwin::WatchOS:
296862987288SDimitry Andric     return SDKVersion >= VersionTuple(11U);
29697a6dacacSDimitry Andric   case Darwin::XROS:
297062987288SDimitry Andric     return SDKVersion >= VersionTuple(2U);
297162987288SDimitry Andric 
297262987288SDimitry Andric   // New SDKs support builtin modules from the start.
29735f757f3fSDimitry Andric   default:
29745f757f3fSDimitry Andric     return true;
29755f757f3fSDimitry Andric   }
29765f757f3fSDimitry Andric }
29775f757f3fSDimitry Andric 
29780fca6ea1SDimitry Andric static inline llvm::VersionTuple
29790fca6ea1SDimitry Andric sizedDeallocMinVersion(llvm::Triple::OSType OS) {
29800fca6ea1SDimitry Andric   switch (OS) {
29810fca6ea1SDimitry Andric   default:
29820fca6ea1SDimitry Andric     break;
29830fca6ea1SDimitry Andric   case llvm::Triple::Darwin:
29840fca6ea1SDimitry Andric   case llvm::Triple::MacOSX: // Earliest supporting version is 10.12.
29850fca6ea1SDimitry Andric     return llvm::VersionTuple(10U, 12U);
29860fca6ea1SDimitry Andric   case llvm::Triple::IOS:
29870fca6ea1SDimitry Andric   case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0.
29880fca6ea1SDimitry Andric     return llvm::VersionTuple(10U);
29890fca6ea1SDimitry Andric   case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0.
29900fca6ea1SDimitry Andric     return llvm::VersionTuple(3U);
29910fca6ea1SDimitry Andric   }
29920fca6ea1SDimitry Andric 
29930fca6ea1SDimitry Andric   llvm_unreachable("Unexpected OS");
29940fca6ea1SDimitry Andric }
29950fca6ea1SDimitry Andric 
29960fca6ea1SDimitry Andric bool Darwin::isSizedDeallocationUnavailable() const {
29970fca6ea1SDimitry Andric   llvm::Triple::OSType OS;
29980fca6ea1SDimitry Andric 
29990fca6ea1SDimitry Andric   if (isTargetMacCatalyst())
30000fca6ea1SDimitry Andric     return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX);
30010fca6ea1SDimitry Andric   switch (TargetPlatform) {
30020fca6ea1SDimitry Andric   case MacOS: // Earlier than 10.12.
30030fca6ea1SDimitry Andric     OS = llvm::Triple::MacOSX;
30040fca6ea1SDimitry Andric     break;
30050fca6ea1SDimitry Andric   case IPhoneOS:
30060fca6ea1SDimitry Andric     OS = llvm::Triple::IOS;
30070fca6ea1SDimitry Andric     break;
30080fca6ea1SDimitry Andric   case TvOS: // Earlier than 10.0.
30090fca6ea1SDimitry Andric     OS = llvm::Triple::TvOS;
30100fca6ea1SDimitry Andric     break;
30110fca6ea1SDimitry Andric   case WatchOS: // Earlier than 3.0.
30120fca6ea1SDimitry Andric     OS = llvm::Triple::WatchOS;
30130fca6ea1SDimitry Andric     break;
30140fca6ea1SDimitry Andric   case DriverKit:
30150fca6ea1SDimitry Andric   case XROS:
30160fca6ea1SDimitry Andric     // Always available.
30170fca6ea1SDimitry Andric     return false;
30180fca6ea1SDimitry Andric   }
30190fca6ea1SDimitry Andric 
30200fca6ea1SDimitry Andric   return TargetVersion < sizedDeallocMinVersion(OS);
30210fca6ea1SDimitry Andric }
30220fca6ea1SDimitry Andric 
30230fca6ea1SDimitry Andric void Darwin::addClangTargetOptions(
30240fca6ea1SDimitry Andric     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
30250b57cec5SDimitry Andric     Action::OffloadKind DeviceOffloadKind) const {
30260b57cec5SDimitry Andric   // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
30270b57cec5SDimitry Andric   // enabled or disabled aligned allocations.
30280b57cec5SDimitry Andric   if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
30290b57cec5SDimitry Andric                                 options::OPT_fno_aligned_allocation) &&
30300b57cec5SDimitry Andric       isAlignedAllocationUnavailable())
30310b57cec5SDimitry Andric     CC1Args.push_back("-faligned-alloc-unavailable");
30320b57cec5SDimitry Andric 
30330fca6ea1SDimitry Andric   // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled
30340fca6ea1SDimitry Andric   // or disabled sized deallocations.
30350fca6ea1SDimitry Andric   if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,
30360fca6ea1SDimitry Andric                                 options::OPT_fno_sized_deallocation) &&
30370fca6ea1SDimitry Andric       isSizedDeallocationUnavailable())
30380fca6ea1SDimitry Andric     CC1Args.push_back("-fno-sized-deallocation");
30390fca6ea1SDimitry Andric 
3040bdd1243dSDimitry Andric   addClangCC1ASTargetOptions(DriverArgs, CC1Args);
3041bdd1243dSDimitry Andric 
3042bdd1243dSDimitry Andric   // Enable compatibility mode for NSItemProviderCompletionHandler in
3043bdd1243dSDimitry Andric   // Foundation/NSItemProvider.h.
3044bdd1243dSDimitry Andric   CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
3045bdd1243dSDimitry Andric 
3046bdd1243dSDimitry Andric   // Give static local variables in inline functions hidden visibility when
3047bdd1243dSDimitry Andric   // -fvisibility-inlines-hidden is enabled.
3048bdd1243dSDimitry Andric   if (!DriverArgs.getLastArgNoClaim(
3049bdd1243dSDimitry Andric           options::OPT_fvisibility_inlines_hidden_static_local_var,
3050bdd1243dSDimitry Andric           options::OPT_fno_visibility_inlines_hidden_static_local_var))
3051bdd1243dSDimitry Andric     CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
30525f757f3fSDimitry Andric 
30535f757f3fSDimitry Andric   // Earlier versions of the darwin SDK have the C standard library headers
30545f757f3fSDimitry Andric   // all together in the Darwin module. That leads to module cycles with
30555f757f3fSDimitry Andric   // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
30565f757f3fSDimitry Andric   // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
30575f757f3fSDimitry Andric   // darwin headers are in the Darwin module, there's a module cycle Darwin ->
30585f757f3fSDimitry Andric   // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
30595f757f3fSDimitry Andric   // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
30605f757f3fSDimitry Andric   // but until then, the builtin headers need to join the system modules.
30615f757f3fSDimitry Andric   // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
30625f757f3fSDimitry Andric   // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
30635f757f3fSDimitry Andric   // to fix the same problem with C++ headers, and is generally fragile.
306462987288SDimitry Andric   if (!sdkSupportsBuiltinModules(TargetPlatform, TargetEnvironment, SDKInfo))
30655f757f3fSDimitry Andric     CC1Args.push_back("-fbuiltin-headers-in-system-modules");
30667a6dacacSDimitry Andric 
30677a6dacacSDimitry Andric   if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,
30687a6dacacSDimitry Andric                                 options::OPT_fno_define_target_os_macros))
30697a6dacacSDimitry Andric     CC1Args.push_back("-fdefine-target-os-macros");
3070bdd1243dSDimitry Andric }
3071bdd1243dSDimitry Andric 
3072bdd1243dSDimitry Andric void Darwin::addClangCC1ASTargetOptions(
3073bdd1243dSDimitry Andric     const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
307481ad6265SDimitry Andric   if (TargetVariantTriple) {
3075bdd1243dSDimitry Andric     CC1ASArgs.push_back("-darwin-target-variant-triple");
3076bdd1243dSDimitry Andric     CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));
307781ad6265SDimitry Andric   }
307881ad6265SDimitry Andric 
30790b57cec5SDimitry Andric   if (SDKInfo) {
30800b57cec5SDimitry Andric     /// Pass the SDK version to the compiler when the SDK information is
30810b57cec5SDimitry Andric     /// available.
3082fe6060f1SDimitry Andric     auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
30830b57cec5SDimitry Andric       std::string Arg;
30840b57cec5SDimitry Andric       llvm::raw_string_ostream OS(Arg);
3085fe6060f1SDimitry Andric       OS << "-target-sdk-version=" << V;
30860fca6ea1SDimitry Andric       CC1ASArgs.push_back(Args.MakeArgString(Arg));
3087fe6060f1SDimitry Andric     };
3088fe6060f1SDimitry Andric 
3089fe6060f1SDimitry Andric     if (isTargetMacCatalyst()) {
3090fe6060f1SDimitry Andric       if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
3091fe6060f1SDimitry Andric               DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3092bdd1243dSDimitry Andric         std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
3093bdd1243dSDimitry Andric             SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
3094bdd1243dSDimitry Andric             std::nullopt);
3095fe6060f1SDimitry Andric         EmitTargetSDKVersionArg(
3096fe6060f1SDimitry Andric             SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
3097fe6060f1SDimitry Andric       }
3098fe6060f1SDimitry Andric     } else {
3099fe6060f1SDimitry Andric       EmitTargetSDKVersionArg(SDKInfo->getVersion());
3100fe6060f1SDimitry Andric     }
310181ad6265SDimitry Andric 
310281ad6265SDimitry Andric     /// Pass the target variant SDK version to the compiler when the SDK
310381ad6265SDimitry Andric     /// information is available and is required for target variant.
310481ad6265SDimitry Andric     if (TargetVariantTriple) {
310581ad6265SDimitry Andric       if (isTargetMacCatalyst()) {
310681ad6265SDimitry Andric         std::string Arg;
310781ad6265SDimitry Andric         llvm::raw_string_ostream OS(Arg);
310881ad6265SDimitry Andric         OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
31090fca6ea1SDimitry Andric         CC1ASArgs.push_back(Args.MakeArgString(Arg));
311081ad6265SDimitry Andric       } else if (const auto *MacOStoMacCatalystMapping =
311181ad6265SDimitry Andric                      SDKInfo->getVersionMapping(
311281ad6265SDimitry Andric                          DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3113bdd1243dSDimitry Andric         if (std::optional<VersionTuple> SDKVersion =
3114bdd1243dSDimitry Andric                 MacOStoMacCatalystMapping->map(
311581ad6265SDimitry Andric                     SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
3116bdd1243dSDimitry Andric                     std::nullopt)) {
311781ad6265SDimitry Andric           std::string Arg;
311881ad6265SDimitry Andric           llvm::raw_string_ostream OS(Arg);
311981ad6265SDimitry Andric           OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
31200fca6ea1SDimitry Andric           CC1ASArgs.push_back(Args.MakeArgString(Arg));
312181ad6265SDimitry Andric         }
312281ad6265SDimitry Andric       }
312381ad6265SDimitry Andric     }
31240b57cec5SDimitry Andric   }
31250b57cec5SDimitry Andric }
31260b57cec5SDimitry Andric 
31270b57cec5SDimitry Andric DerivedArgList *
31280b57cec5SDimitry Andric Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
31290b57cec5SDimitry Andric                       Action::OffloadKind DeviceOffloadKind) const {
31300b57cec5SDimitry Andric   // First get the generic Apple args, before moving onto Darwin-specific ones.
31310b57cec5SDimitry Andric   DerivedArgList *DAL =
31320b57cec5SDimitry Andric       MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
31330b57cec5SDimitry Andric 
31340b57cec5SDimitry Andric   // If no architecture is bound, none of the translations here are relevant.
31350b57cec5SDimitry Andric   if (BoundArch.empty())
31360b57cec5SDimitry Andric     return DAL;
31370b57cec5SDimitry Andric 
31380b57cec5SDimitry Andric   // Add an explicit version min argument for the deployment target. We do this
31390b57cec5SDimitry Andric   // after argument translation because -Xarch_ arguments may add a version min
31400b57cec5SDimitry Andric   // argument.
31410b57cec5SDimitry Andric   AddDeploymentTarget(*DAL);
31420b57cec5SDimitry Andric 
31430b57cec5SDimitry Andric   // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
31440b57cec5SDimitry Andric   // FIXME: It would be far better to avoid inserting those -static arguments,
31450b57cec5SDimitry Andric   // but we can't check the deployment target in the translation code until
31460b57cec5SDimitry Andric   // it is set here.
31477a6dacacSDimitry Andric   if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||
31480b57cec5SDimitry Andric       (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
31490b57cec5SDimitry Andric     for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
31500b57cec5SDimitry Andric       Arg *A = *it;
31510b57cec5SDimitry Andric       ++it;
31520b57cec5SDimitry Andric       if (A->getOption().getID() != options::OPT_mkernel &&
31530b57cec5SDimitry Andric           A->getOption().getID() != options::OPT_fapple_kext)
31540b57cec5SDimitry Andric         continue;
31550b57cec5SDimitry Andric       assert(it != ie && "unexpected argument translation");
31560b57cec5SDimitry Andric       A = *it;
31570b57cec5SDimitry Andric       assert(A->getOption().getID() == options::OPT_static &&
31580b57cec5SDimitry Andric              "missing expected -static argument");
31590b57cec5SDimitry Andric       *it = nullptr;
31600b57cec5SDimitry Andric       ++it;
31610b57cec5SDimitry Andric     }
31620b57cec5SDimitry Andric   }
31630b57cec5SDimitry Andric 
31640b57cec5SDimitry Andric   auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
31650b57cec5SDimitry Andric   if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
31660b57cec5SDimitry Andric     if (Args.hasFlag(options::OPT_fomit_frame_pointer,
31670b57cec5SDimitry Andric                      options::OPT_fno_omit_frame_pointer, false))
31680b57cec5SDimitry Andric       getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
31690b57cec5SDimitry Andric           << "-fomit-frame-pointer" << BoundArch;
31700b57cec5SDimitry Andric   }
31710b57cec5SDimitry Andric 
31720b57cec5SDimitry Andric   return DAL;
31730b57cec5SDimitry Andric }
31740b57cec5SDimitry Andric 
3175bdd1243dSDimitry Andric ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
31760b57cec5SDimitry Andric   // Unwind tables are not emitted if -fno-exceptions is supplied (except when
31770b57cec5SDimitry Andric   // targeting x86_64).
3178bdd1243dSDimitry Andric   if (getArch() == llvm::Triple::x86_64 ||
31790b57cec5SDimitry Andric       (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
31800b57cec5SDimitry Andric        Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
3181bdd1243dSDimitry Andric                     true)))
318206c3fb27SDimitry Andric     return (getArch() == llvm::Triple::aarch64 ||
318306c3fb27SDimitry Andric             getArch() == llvm::Triple::aarch64_32)
318406c3fb27SDimitry Andric                ? UnwindTableLevel::Synchronous
3185bdd1243dSDimitry Andric                : UnwindTableLevel::Asynchronous;
3186bdd1243dSDimitry Andric 
3187bdd1243dSDimitry Andric   return UnwindTableLevel::None;
31880b57cec5SDimitry Andric }
31890b57cec5SDimitry Andric 
31900b57cec5SDimitry Andric bool MachO::UseDwarfDebugFlags() const {
31910b57cec5SDimitry Andric   if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
31920b57cec5SDimitry Andric     return S[0] != '\0';
31930b57cec5SDimitry Andric   return false;
31940b57cec5SDimitry Andric }
31950b57cec5SDimitry Andric 
319681ad6265SDimitry Andric std::string MachO::GetGlobalDebugPathRemapping() const {
319781ad6265SDimitry Andric   if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))
319881ad6265SDimitry Andric     return S;
319981ad6265SDimitry Andric   return {};
320081ad6265SDimitry Andric }
320181ad6265SDimitry Andric 
32020b57cec5SDimitry Andric llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
32030b57cec5SDimitry Andric   // Darwin uses SjLj exceptions on ARM.
32040b57cec5SDimitry Andric   if (getTriple().getArch() != llvm::Triple::arm &&
32050b57cec5SDimitry Andric       getTriple().getArch() != llvm::Triple::thumb)
32060b57cec5SDimitry Andric     return llvm::ExceptionHandling::None;
32070b57cec5SDimitry Andric 
32080b57cec5SDimitry Andric   // Only watchOS uses the new DWARF/Compact unwinding method.
32090b57cec5SDimitry Andric   llvm::Triple Triple(ComputeLLVMTriple(Args));
32100b57cec5SDimitry Andric   if (Triple.isWatchABI())
32110b57cec5SDimitry Andric     return llvm::ExceptionHandling::DwarfCFI;
32120b57cec5SDimitry Andric 
32130b57cec5SDimitry Andric   return llvm::ExceptionHandling::SjLj;
32140b57cec5SDimitry Andric }
32150b57cec5SDimitry Andric 
32160b57cec5SDimitry Andric bool Darwin::SupportsEmbeddedBitcode() const {
32170b57cec5SDimitry Andric   assert(TargetInitialized && "Target not initialized!");
32180b57cec5SDimitry Andric   if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
32190b57cec5SDimitry Andric     return false;
32200b57cec5SDimitry Andric   return true;
32210b57cec5SDimitry Andric }
32220b57cec5SDimitry Andric 
32230b57cec5SDimitry Andric bool MachO::isPICDefault() const { return true; }
32240b57cec5SDimitry Andric 
3225349cc55cSDimitry Andric bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
32260b57cec5SDimitry Andric 
32270b57cec5SDimitry Andric bool MachO::isPICDefaultForced() const {
32280b57cec5SDimitry Andric   return (getArch() == llvm::Triple::x86_64 ||
32290b57cec5SDimitry Andric           getArch() == llvm::Triple::aarch64);
32300b57cec5SDimitry Andric }
32310b57cec5SDimitry Andric 
32320b57cec5SDimitry Andric bool MachO::SupportsProfiling() const {
32330b57cec5SDimitry Andric   // Profiling instrumentation is only supported on x86.
3234480093f4SDimitry Andric   return getTriple().isX86();
32350b57cec5SDimitry Andric }
32360b57cec5SDimitry Andric 
32370b57cec5SDimitry Andric void Darwin::addMinVersionArgs(const ArgList &Args,
32380b57cec5SDimitry Andric                                ArgStringList &CmdArgs) const {
3239fe6060f1SDimitry Andric   VersionTuple TargetVersion = getTripleTargetVersion();
32400b57cec5SDimitry Andric 
32417a6dacacSDimitry Andric   assert(!isTargetXROS() && "xrOS always uses -platform-version");
32427a6dacacSDimitry Andric 
32430b57cec5SDimitry Andric   if (isTargetWatchOS())
32440b57cec5SDimitry Andric     CmdArgs.push_back("-watchos_version_min");
32450b57cec5SDimitry Andric   else if (isTargetWatchOSSimulator())
32460b57cec5SDimitry Andric     CmdArgs.push_back("-watchos_simulator_version_min");
32470b57cec5SDimitry Andric   else if (isTargetTvOS())
32480b57cec5SDimitry Andric     CmdArgs.push_back("-tvos_version_min");
32490b57cec5SDimitry Andric   else if (isTargetTvOSSimulator())
32500b57cec5SDimitry Andric     CmdArgs.push_back("-tvos_simulator_version_min");
325181ad6265SDimitry Andric   else if (isTargetDriverKit())
325281ad6265SDimitry Andric     CmdArgs.push_back("-driverkit_version_min");
32530b57cec5SDimitry Andric   else if (isTargetIOSSimulator())
32540b57cec5SDimitry Andric     CmdArgs.push_back("-ios_simulator_version_min");
32550b57cec5SDimitry Andric   else if (isTargetIOSBased())
32560b57cec5SDimitry Andric     CmdArgs.push_back("-iphoneos_version_min");
3257fe6060f1SDimitry Andric   else if (isTargetMacCatalyst())
3258fe6060f1SDimitry Andric     CmdArgs.push_back("-maccatalyst_version_min");
32590b57cec5SDimitry Andric   else {
32600b57cec5SDimitry Andric     assert(isTargetMacOS() && "unexpected target");
32610b57cec5SDimitry Andric     CmdArgs.push_back("-macosx_version_min");
32620b57cec5SDimitry Andric   }
32630b57cec5SDimitry Andric 
32645ffd83dbSDimitry Andric   VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
32655ffd83dbSDimitry Andric   if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
32665ffd83dbSDimitry Andric     TargetVersion = MinTgtVers;
32670b57cec5SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
326881ad6265SDimitry Andric   if (TargetVariantTriple) {
326981ad6265SDimitry Andric     assert(isTargetMacOSBased() && "unexpected target");
327081ad6265SDimitry Andric     VersionTuple VariantTargetVersion;
327181ad6265SDimitry Andric     if (TargetVariantTriple->isMacOSX()) {
327281ad6265SDimitry Andric       CmdArgs.push_back("-macosx_version_min");
327381ad6265SDimitry Andric       TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);
327481ad6265SDimitry Andric     } else {
327581ad6265SDimitry Andric       assert(TargetVariantTriple->isiOS() &&
327681ad6265SDimitry Andric              TargetVariantTriple->isMacCatalystEnvironment() &&
327781ad6265SDimitry Andric              "unexpected target variant triple");
327881ad6265SDimitry Andric       CmdArgs.push_back("-maccatalyst_version_min");
327981ad6265SDimitry Andric       VariantTargetVersion = TargetVariantTriple->getiOSVersion();
328081ad6265SDimitry Andric     }
328181ad6265SDimitry Andric     VersionTuple MinTgtVers =
328281ad6265SDimitry Andric         TargetVariantTriple->getMinimumSupportedOSVersion();
328381ad6265SDimitry Andric     if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
328481ad6265SDimitry Andric       VariantTargetVersion = MinTgtVers;
328581ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));
328681ad6265SDimitry Andric   }
32870b57cec5SDimitry Andric }
32880b57cec5SDimitry Andric 
3289480093f4SDimitry Andric static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
3290480093f4SDimitry Andric                                    Darwin::DarwinEnvironmentKind Environment) {
3291480093f4SDimitry Andric   switch (Platform) {
3292480093f4SDimitry Andric   case Darwin::MacOS:
3293480093f4SDimitry Andric     return "macos";
3294480093f4SDimitry Andric   case Darwin::IPhoneOS:
3295fe6060f1SDimitry Andric     if (Environment == Darwin::MacCatalyst)
3296fe6060f1SDimitry Andric       return "mac catalyst";
3297480093f4SDimitry Andric     return "ios";
3298480093f4SDimitry Andric   case Darwin::TvOS:
3299480093f4SDimitry Andric     return "tvos";
3300480093f4SDimitry Andric   case Darwin::WatchOS:
3301480093f4SDimitry Andric     return "watchos";
33027a6dacacSDimitry Andric   case Darwin::XROS:
33037a6dacacSDimitry Andric     return "xros";
330481ad6265SDimitry Andric   case Darwin::DriverKit:
330581ad6265SDimitry Andric     return "driverkit";
3306480093f4SDimitry Andric   }
3307480093f4SDimitry Andric   llvm_unreachable("invalid platform");
3308480093f4SDimitry Andric }
3309480093f4SDimitry Andric 
3310480093f4SDimitry Andric void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
3311480093f4SDimitry Andric                                     llvm::opt::ArgStringList &CmdArgs) const {
331281ad6265SDimitry Andric   auto EmitPlatformVersionArg =
331381ad6265SDimitry Andric       [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
331481ad6265SDimitry Andric           Darwin::DarwinEnvironmentKind TargetEnvironment,
331581ad6265SDimitry Andric           const llvm::Triple &TT) {
3316480093f4SDimitry Andric         // -platform_version <platform> <target_version> <sdk_version>
3317480093f4SDimitry Andric         // Both the target and SDK version support only up to 3 components.
3318480093f4SDimitry Andric         CmdArgs.push_back("-platform_version");
331981ad6265SDimitry Andric         std::string PlatformName =
332081ad6265SDimitry Andric             getPlatformName(TargetPlatform, TargetEnvironment);
3321480093f4SDimitry Andric         if (TargetEnvironment == Darwin::Simulator)
3322480093f4SDimitry Andric           PlatformName += "-simulator";
3323480093f4SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(PlatformName));
332481ad6265SDimitry Andric         VersionTuple TargetVersion = TV.withoutBuild();
332581ad6265SDimitry Andric         if ((TargetPlatform == Darwin::IPhoneOS ||
332681ad6265SDimitry Andric              TargetPlatform == Darwin::TvOS) &&
332781ad6265SDimitry Andric             getTriple().getArchName() == "arm64e" &&
332881ad6265SDimitry Andric             TargetVersion.getMajor() < 14) {
332981ad6265SDimitry Andric           // arm64e slice is supported on iOS/tvOS 14+ only.
333081ad6265SDimitry Andric           TargetVersion = VersionTuple(14, 0);
333181ad6265SDimitry Andric         }
333281ad6265SDimitry Andric         VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
33335ffd83dbSDimitry Andric         if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
33345ffd83dbSDimitry Andric           TargetVersion = MinTgtVers;
3335480093f4SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3336fe6060f1SDimitry Andric 
333781ad6265SDimitry Andric         if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
3338fe6060f1SDimitry Andric           // Mac Catalyst programs must use the appropriate iOS SDK version
3339fe6060f1SDimitry Andric           // that corresponds to the macOS SDK version used for the compilation.
3340bdd1243dSDimitry Andric           std::optional<VersionTuple> iOSSDKVersion;
3341fe6060f1SDimitry Andric           if (SDKInfo) {
334281ad6265SDimitry Andric             if (const auto *MacOStoMacCatalystMapping =
334381ad6265SDimitry Andric                     SDKInfo->getVersionMapping(
3344fe6060f1SDimitry Andric                         DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3345fe6060f1SDimitry Andric               iOSSDKVersion = MacOStoMacCatalystMapping->map(
3346fe6060f1SDimitry Andric                   SDKInfo->getVersion().withoutBuild(),
3347bdd1243dSDimitry Andric                   minimumMacCatalystDeploymentTarget(), std::nullopt);
3348fe6060f1SDimitry Andric             }
3349fe6060f1SDimitry Andric           }
3350fe6060f1SDimitry Andric           CmdArgs.push_back(Args.MakeArgString(
335181ad6265SDimitry Andric               (iOSSDKVersion ? *iOSSDKVersion
335281ad6265SDimitry Andric                              : minimumMacCatalystDeploymentTarget())
3353fe6060f1SDimitry Andric                   .getAsString()));
3354fe6060f1SDimitry Andric           return;
3355fe6060f1SDimitry Andric         }
3356fe6060f1SDimitry Andric 
3357480093f4SDimitry Andric         if (SDKInfo) {
3358480093f4SDimitry Andric           VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
3359bdd1243dSDimitry Andric           if (!SDKVersion.getMinor())
3360bdd1243dSDimitry Andric             SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
3361480093f4SDimitry Andric           CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
3362480093f4SDimitry Andric         } else {
3363fe6060f1SDimitry Andric           // Use an SDK version that's matching the deployment target if the SDK
336481ad6265SDimitry Andric           // version is missing. This is preferred over an empty SDK version
336581ad6265SDimitry Andric           // (0.0.0) as the system's runtime might expect the linked binary to
336681ad6265SDimitry Andric           // contain a valid SDK version in order for the binary to work
336781ad6265SDimitry Andric           // correctly. It's reasonable to use the deployment target version as
336881ad6265SDimitry Andric           // a proxy for the SDK version because older SDKs don't guarantee
336981ad6265SDimitry Andric           // support for deployment targets newer than the SDK versions, so that
337081ad6265SDimitry Andric           // rules out using some predetermined older SDK version, which leaves
337181ad6265SDimitry Andric           // the deployment target version as the only reasonable choice.
3372fe6060f1SDimitry Andric           CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3373480093f4SDimitry Andric         }
337481ad6265SDimitry Andric       };
337581ad6265SDimitry Andric   EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
337681ad6265SDimitry Andric                          TargetEnvironment, getEffectiveTriple());
337781ad6265SDimitry Andric   if (!TargetVariantTriple)
337881ad6265SDimitry Andric     return;
337981ad6265SDimitry Andric   Darwin::DarwinPlatformKind Platform;
338081ad6265SDimitry Andric   Darwin::DarwinEnvironmentKind Environment;
338181ad6265SDimitry Andric   VersionTuple TargetVariantVersion;
338281ad6265SDimitry Andric   if (TargetVariantTriple->isMacOSX()) {
338381ad6265SDimitry Andric     TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);
338481ad6265SDimitry Andric     Platform = Darwin::MacOS;
338581ad6265SDimitry Andric     Environment = Darwin::NativeEnvironment;
338681ad6265SDimitry Andric   } else {
338781ad6265SDimitry Andric     assert(TargetVariantTriple->isiOS() &&
338881ad6265SDimitry Andric            TargetVariantTriple->isMacCatalystEnvironment() &&
338981ad6265SDimitry Andric            "unexpected target variant triple");
339081ad6265SDimitry Andric     TargetVariantVersion = TargetVariantTriple->getiOSVersion();
339181ad6265SDimitry Andric     Platform = Darwin::IPhoneOS;
339281ad6265SDimitry Andric     Environment = Darwin::MacCatalyst;
339381ad6265SDimitry Andric   }
339481ad6265SDimitry Andric   EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
339581ad6265SDimitry Andric                          *TargetVariantTriple);
3396480093f4SDimitry Andric }
3397480093f4SDimitry Andric 
33985ffd83dbSDimitry Andric // Add additional link args for the -dynamiclib option.
33995ffd83dbSDimitry Andric static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
34005ffd83dbSDimitry Andric                                   ArgStringList &CmdArgs) {
34010b57cec5SDimitry Andric   // Derived from darwin_dylib1 spec.
34025ffd83dbSDimitry Andric   if (D.isTargetIPhoneOS()) {
34035ffd83dbSDimitry Andric     if (D.isIPhoneOSVersionLT(3, 1))
34040b57cec5SDimitry Andric       CmdArgs.push_back("-ldylib1.o");
34055ffd83dbSDimitry Andric     return;
34065ffd83dbSDimitry Andric   }
34075ffd83dbSDimitry Andric 
34085ffd83dbSDimitry Andric   if (!D.isTargetMacOS())
34095ffd83dbSDimitry Andric     return;
34105ffd83dbSDimitry Andric   if (D.isMacosxVersionLT(10, 5))
34110b57cec5SDimitry Andric     CmdArgs.push_back("-ldylib1.o");
34125ffd83dbSDimitry Andric   else if (D.isMacosxVersionLT(10, 6))
34130b57cec5SDimitry Andric     CmdArgs.push_back("-ldylib1.10.5.o");
34140b57cec5SDimitry Andric }
34155ffd83dbSDimitry Andric 
34165ffd83dbSDimitry Andric // Add additional link args for the -bundle option.
34175ffd83dbSDimitry Andric static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
34185ffd83dbSDimitry Andric                               ArgStringList &CmdArgs) {
34195ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_static))
34205ffd83dbSDimitry Andric     return;
34210b57cec5SDimitry Andric   // Derived from darwin_bundle1 spec.
34225ffd83dbSDimitry Andric   if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
34235ffd83dbSDimitry Andric       (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
34240b57cec5SDimitry Andric     CmdArgs.push_back("-lbundle1.o");
34250b57cec5SDimitry Andric }
34265ffd83dbSDimitry Andric 
34275ffd83dbSDimitry Andric // Add additional link args for the -pg option.
34285ffd83dbSDimitry Andric static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
34295ffd83dbSDimitry Andric                                    ArgStringList &CmdArgs) {
34305ffd83dbSDimitry Andric   if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
34315ffd83dbSDimitry Andric     if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
34320b57cec5SDimitry Andric         Args.hasArg(options::OPT_preload)) {
34330b57cec5SDimitry Andric       CmdArgs.push_back("-lgcrt0.o");
34340b57cec5SDimitry Andric     } else {
34350b57cec5SDimitry Andric       CmdArgs.push_back("-lgcrt1.o");
34360b57cec5SDimitry Andric 
34370b57cec5SDimitry Andric       // darwin_crt2 spec is empty.
34380b57cec5SDimitry Andric     }
34390b57cec5SDimitry Andric     // By default on OS X 10.8 and later, we don't link with a crt1.o
34400b57cec5SDimitry Andric     // file and the linker knows to use _main as the entry point.  But,
34410b57cec5SDimitry Andric     // when compiling with -pg, we need to link with the gcrt1.o file,
34420b57cec5SDimitry Andric     // so pass the -no_new_main option to tell the linker to use the
34430b57cec5SDimitry Andric     // "start" symbol as the entry point.
34445ffd83dbSDimitry Andric     if (!D.isMacosxVersionLT(10, 8))
34450b57cec5SDimitry Andric       CmdArgs.push_back("-no_new_main");
34460b57cec5SDimitry Andric   } else {
34475ffd83dbSDimitry Andric     D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
3448fe6060f1SDimitry Andric         << D.isTargetMacOSBased();
34490b57cec5SDimitry Andric   }
34505ffd83dbSDimitry Andric }
34510b57cec5SDimitry Andric 
34525ffd83dbSDimitry Andric static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
34535ffd83dbSDimitry Andric                                   ArgStringList &CmdArgs) {
34545ffd83dbSDimitry Andric   // Derived from darwin_crt1 spec.
34555ffd83dbSDimitry Andric   if (D.isTargetIPhoneOS()) {
34565ffd83dbSDimitry Andric     if (D.getArch() == llvm::Triple::aarch64)
34575ffd83dbSDimitry Andric       ; // iOS does not need any crt1 files for arm64
34585ffd83dbSDimitry Andric     else if (D.isIPhoneOSVersionLT(3, 1))
34595ffd83dbSDimitry Andric       CmdArgs.push_back("-lcrt1.o");
34605ffd83dbSDimitry Andric     else if (D.isIPhoneOSVersionLT(6, 0))
34615ffd83dbSDimitry Andric       CmdArgs.push_back("-lcrt1.3.1.o");
34625ffd83dbSDimitry Andric     return;
34635ffd83dbSDimitry Andric   }
34645ffd83dbSDimitry Andric 
34655ffd83dbSDimitry Andric   if (!D.isTargetMacOS())
34665ffd83dbSDimitry Andric     return;
34675ffd83dbSDimitry Andric   if (D.isMacosxVersionLT(10, 5))
34685ffd83dbSDimitry Andric     CmdArgs.push_back("-lcrt1.o");
34695ffd83dbSDimitry Andric   else if (D.isMacosxVersionLT(10, 6))
34705ffd83dbSDimitry Andric     CmdArgs.push_back("-lcrt1.10.5.o");
34715ffd83dbSDimitry Andric   else if (D.isMacosxVersionLT(10, 8))
34725ffd83dbSDimitry Andric     CmdArgs.push_back("-lcrt1.10.6.o");
34730b57cec5SDimitry Andric   // darwin_crt2 spec is empty.
34740b57cec5SDimitry Andric }
34750b57cec5SDimitry Andric 
34765ffd83dbSDimitry Andric void Darwin::addStartObjectFileArgs(const ArgList &Args,
34775ffd83dbSDimitry Andric                                     ArgStringList &CmdArgs) const {
34785ffd83dbSDimitry Andric   // Derived from startfile spec.
34795ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_dynamiclib))
34805ffd83dbSDimitry Andric     addDynamicLibLinkArgs(*this, Args, CmdArgs);
34815ffd83dbSDimitry Andric   else if (Args.hasArg(options::OPT_bundle))
34825ffd83dbSDimitry Andric     addBundleLinkArgs(*this, Args, CmdArgs);
34835ffd83dbSDimitry Andric   else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
34845ffd83dbSDimitry Andric     addPgProfilingLinkArgs(*this, Args, CmdArgs);
34855ffd83dbSDimitry Andric   else if (Args.hasArg(options::OPT_static) ||
34865ffd83dbSDimitry Andric            Args.hasArg(options::OPT_object) ||
34875ffd83dbSDimitry Andric            Args.hasArg(options::OPT_preload))
34885ffd83dbSDimitry Andric     CmdArgs.push_back("-lcrt0.o");
34895ffd83dbSDimitry Andric   else
34905ffd83dbSDimitry Andric     addDefaultCRTLinkArgs(*this, Args, CmdArgs);
34915ffd83dbSDimitry Andric 
34925ffd83dbSDimitry Andric   if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
34935ffd83dbSDimitry Andric       isMacosxVersionLT(10, 5)) {
34940b57cec5SDimitry Andric     const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
34950b57cec5SDimitry Andric     CmdArgs.push_back(Str);
34960b57cec5SDimitry Andric   }
34970b57cec5SDimitry Andric }
34980b57cec5SDimitry Andric 
34990b57cec5SDimitry Andric void Darwin::CheckObjCARC() const {
35007a6dacacSDimitry Andric   if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||
3501fe6060f1SDimitry Andric       (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
35020b57cec5SDimitry Andric     return;
35030b57cec5SDimitry Andric   getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
35040b57cec5SDimitry Andric }
35050b57cec5SDimitry Andric 
35060b57cec5SDimitry Andric SanitizerMask Darwin::getSupportedSanitizers() const {
35070b57cec5SDimitry Andric   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
3508e8d8bef9SDimitry Andric   const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
35090b57cec5SDimitry Andric   SanitizerMask Res = ToolChain::getSupportedSanitizers();
35100b57cec5SDimitry Andric   Res |= SanitizerKind::Address;
35110b57cec5SDimitry Andric   Res |= SanitizerKind::PointerCompare;
35120b57cec5SDimitry Andric   Res |= SanitizerKind::PointerSubtract;
35130b57cec5SDimitry Andric   Res |= SanitizerKind::Leak;
35140b57cec5SDimitry Andric   Res |= SanitizerKind::Fuzzer;
35150b57cec5SDimitry Andric   Res |= SanitizerKind::FuzzerNoLink;
35165ffd83dbSDimitry Andric   Res |= SanitizerKind::ObjCCast;
35170b57cec5SDimitry Andric 
35180b57cec5SDimitry Andric   // Prior to 10.9, macOS shipped a version of the C++ standard library without
35190b57cec5SDimitry Andric   // C++11 support. The same is true of iOS prior to version 5. These OS'es are
35200b57cec5SDimitry Andric   // incompatible with -fsanitize=vptr.
3521fe6060f1SDimitry Andric   if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&
3522fe6060f1SDimitry Andric       !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
35230b57cec5SDimitry Andric     Res |= SanitizerKind::Vptr;
35240b57cec5SDimitry Andric 
3525bdd1243dSDimitry Andric   if ((IsX86_64 || IsAArch64) &&
3526bdd1243dSDimitry Andric       (isTargetMacOSBased() || isTargetIOSSimulator() ||
3527bdd1243dSDimitry Andric        isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
35280b57cec5SDimitry Andric     Res |= SanitizerKind::Thread;
35290b57cec5SDimitry Andric   }
35300fca6ea1SDimitry Andric 
35310fca6ea1SDimitry Andric   if (IsX86_64)
35320fca6ea1SDimitry Andric     Res |= SanitizerKind::NumericalStability;
35330fca6ea1SDimitry Andric 
35340b57cec5SDimitry Andric   return Res;
35350b57cec5SDimitry Andric }
35360b57cec5SDimitry Andric 
35370b57cec5SDimitry Andric void Darwin::printVerboseInfo(raw_ostream &OS) const {
35387a6dacacSDimitry Andric   CudaInstallation->print(OS);
35397a6dacacSDimitry Andric   RocmInstallation->print(OS);
35400b57cec5SDimitry Andric }
3541