xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp (revision 6c4b055cfb6bf549e9145dde6454cc6b178c35e4)
1  //===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  
9  #include "Darwin.h"
10  #include "Arch/AArch64.h"
11  #include "Arch/ARM.h"
12  #include "CommonArgs.h"
13  #include "clang/Basic/AlignedAllocation.h"
14  #include "clang/Basic/ObjCRuntime.h"
15  #include "clang/Config/config.h"
16  #include "clang/Driver/Compilation.h"
17  #include "clang/Driver/Driver.h"
18  #include "clang/Driver/DriverDiagnostic.h"
19  #include "clang/Driver/Options.h"
20  #include "clang/Driver/SanitizerArgs.h"
21  #include "llvm/ADT/StringSwitch.h"
22  #include "llvm/Option/ArgList.h"
23  #include "llvm/ProfileData/InstrProf.h"
24  #include "llvm/Support/Path.h"
25  #include "llvm/Support/ScopedPrinter.h"
26  #include "llvm/Support/Threading.h"
27  #include "llvm/Support/VirtualFileSystem.h"
28  #include "llvm/TargetParser/TargetParser.h"
29  #include "llvm/TargetParser/Triple.h"
30  #include <cstdlib> // ::getenv
31  
32  using namespace clang::driver;
33  using namespace clang::driver::tools;
34  using namespace clang::driver::toolchains;
35  using namespace clang;
36  using namespace llvm::opt;
37  
minimumMacCatalystDeploymentTarget()38  static VersionTuple minimumMacCatalystDeploymentTarget() {
39    return VersionTuple(13, 1);
40  }
41  
getArchTypeForMachOArchName(StringRef Str)42  llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
43    // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
44    // archs which Darwin doesn't use.
45  
46    // The matching this routine does is fairly pointless, since it is neither the
47    // complete architecture list, nor a reasonable subset. The problem is that
48    // historically the driver accepts this and also ties its -march=
49    // handling to the architecture name, so we need to be careful before removing
50    // support for it.
51  
52    // This code must be kept in sync with Clang's Darwin specific argument
53    // translation.
54  
55    return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
56        .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
57        .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
58               llvm::Triple::x86)
59        .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
60        // This is derived from the driver.
61        .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
62        .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
63        .Cases("armv7s", "xscale", llvm::Triple::arm)
64        .Cases("arm64", "arm64e", llvm::Triple::aarch64)
65        .Case("arm64_32", llvm::Triple::aarch64_32)
66        .Case("r600", llvm::Triple::r600)
67        .Case("amdgcn", llvm::Triple::amdgcn)
68        .Case("nvptx", llvm::Triple::nvptx)
69        .Case("nvptx64", llvm::Triple::nvptx64)
70        .Case("amdil", llvm::Triple::amdil)
71        .Case("spir", llvm::Triple::spir)
72        .Default(llvm::Triple::UnknownArch);
73  }
74  
setTripleTypeForMachOArchName(llvm::Triple & T,StringRef Str,const ArgList & Args)75  void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,
76                                             const ArgList &Args) {
77    const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
78    llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
79    T.setArch(Arch);
80    if (Arch != llvm::Triple::UnknownArch)
81      T.setArchName(Str);
82  
83    if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
84        ArchKind == llvm::ARM::ArchKind::ARMV7M ||
85        ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
86      // Don't reject these -version-min= if we have the appropriate triple.
87      if (T.getOS() == llvm::Triple::IOS)
88        for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ))
89          A->ignoreTargetSpecific();
90      if (T.getOS() == llvm::Triple::WatchOS)
91        for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))
92          A->ignoreTargetSpecific();
93      if (T.getOS() == llvm::Triple::TvOS)
94        for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))
95          A->ignoreTargetSpecific();
96  
97      T.setOS(llvm::Triple::UnknownOS);
98      T.setObjectFormat(llvm::Triple::MachO);
99    }
100  }
101  
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const102  void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
103                                       const InputInfo &Output,
104                                       const InputInfoList &Inputs,
105                                       const ArgList &Args,
106                                       const char *LinkingOutput) const {
107    const llvm::Triple &T(getToolChain().getTriple());
108  
109    ArgStringList CmdArgs;
110  
111    assert(Inputs.size() == 1 && "Unexpected number of inputs.");
112    const InputInfo &Input = Inputs[0];
113  
114    // Determine the original source input.
115    const Action *SourceAction = &JA;
116    while (SourceAction->getKind() != Action::InputClass) {
117      assert(!SourceAction->getInputs().empty() && "unexpected root action!");
118      SourceAction = SourceAction->getInputs()[0];
119    }
120  
121    // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
122    // sure it runs its system assembler not clang's integrated assembler.
123    // Applicable to darwin11+ and Xcode 4+.  darwin<10 lacked integrated-as.
124    // FIXME: at run-time detect assembler capabilities or rely on version
125    // information forwarded by -target-assembler-version.
126    if (Args.hasArg(options::OPT_fno_integrated_as)) {
127      if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
128        CmdArgs.push_back("-Q");
129    }
130  
131    // Forward -g, assuming we are dealing with an actual assembly file.
132    if (SourceAction->getType() == types::TY_Asm ||
133        SourceAction->getType() == types::TY_PP_Asm) {
134      if (Args.hasArg(options::OPT_gstabs))
135        CmdArgs.push_back("--gstabs");
136      else if (Args.hasArg(options::OPT_g_Group))
137        CmdArgs.push_back("-g");
138    }
139  
140    // Derived from asm spec.
141    AddMachOArch(Args, CmdArgs);
142  
143    // Use -force_cpusubtype_ALL on x86 by default.
144    if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))
145      CmdArgs.push_back("-force_cpusubtype_ALL");
146  
147    if (getToolChain().getArch() != llvm::Triple::x86_64 &&
148        (((Args.hasArg(options::OPT_mkernel) ||
149           Args.hasArg(options::OPT_fapple_kext)) &&
150          getMachOToolChain().isKernelStatic()) ||
151         Args.hasArg(options::OPT_static)))
152      CmdArgs.push_back("-static");
153  
154    Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
155  
156    assert(Output.isFilename() && "Unexpected lipo output.");
157    CmdArgs.push_back("-o");
158    CmdArgs.push_back(Output.getFilename());
159  
160    assert(Input.isFilename() && "Invalid input.");
161    CmdArgs.push_back(Input.getFilename());
162  
163    // asm_final spec is empty.
164  
165    const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
166    C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
167                                           Exec, CmdArgs, Inputs, Output));
168  }
169  
anchor()170  void darwin::MachOTool::anchor() {}
171  
AddMachOArch(const ArgList & Args,ArgStringList & CmdArgs) const172  void darwin::MachOTool::AddMachOArch(const ArgList &Args,
173                                       ArgStringList &CmdArgs) const {
174    StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
175  
176    // Derived from darwin_arch spec.
177    CmdArgs.push_back("-arch");
178    CmdArgs.push_back(Args.MakeArgString(ArchName));
179  
180    // FIXME: Is this needed anymore?
181    if (ArchName == "arm")
182      CmdArgs.push_back("-force_cpusubtype_ALL");
183  }
184  
NeedsTempPath(const InputInfoList & Inputs) const185  bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
186    // We only need to generate a temp path for LTO if we aren't compiling object
187    // files. When compiling source files, we run 'dsymutil' after linking. We
188    // don't run 'dsymutil' when compiling object files.
189    for (const auto &Input : Inputs)
190      if (Input.getType() != types::TY_Object)
191        return true;
192  
193    return false;
194  }
195  
196  /// Pass -no_deduplicate to ld64 under certain conditions:
197  ///
198  /// - Either -O0 or -O1 is explicitly specified
199  /// - No -O option is specified *and* this is a compile+link (implicit -O0)
200  ///
201  /// Also do *not* add -no_deduplicate when no -O option is specified and this
202  /// is just a link (we can't imply -O0)
shouldLinkerNotDedup(bool IsLinkerOnlyAction,const ArgList & Args)203  static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
204    if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
205      if (A->getOption().matches(options::OPT_O0))
206        return true;
207      if (A->getOption().matches(options::OPT_O))
208        return llvm::StringSwitch<bool>(A->getValue())
209                      .Case("1", true)
210                      .Default(false);
211      return false; // OPT_Ofast & OPT_O4
212    }
213  
214    if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
215      return true;
216    return false;
217  }
218  
AddLinkArgs(Compilation & C,const ArgList & Args,ArgStringList & CmdArgs,const InputInfoList & Inputs,VersionTuple Version,bool LinkerIsLLD,bool UsePlatformVersion) const219  void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
220                                   ArgStringList &CmdArgs,
221                                   const InputInfoList &Inputs,
222                                   VersionTuple Version, bool LinkerIsLLD,
223                                   bool UsePlatformVersion) const {
224    const Driver &D = getToolChain().getDriver();
225    const toolchains::MachO &MachOTC = getMachOToolChain();
226  
227    // Newer linkers support -demangle. Pass it if supported and not disabled by
228    // the user.
229    if ((Version >= VersionTuple(100) || LinkerIsLLD) &&
230        !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
231      CmdArgs.push_back("-demangle");
232  
233    if (Args.hasArg(options::OPT_rdynamic) &&
234        (Version >= VersionTuple(137) || LinkerIsLLD))
235      CmdArgs.push_back("-export_dynamic");
236  
237    // If we are using App Extension restrictions, pass a flag to the linker
238    // telling it that the compiled code has been audited.
239    if (Args.hasFlag(options::OPT_fapplication_extension,
240                     options::OPT_fno_application_extension, false))
241      CmdArgs.push_back("-application_extension");
242  
243    if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&
244        NeedsTempPath(Inputs)) {
245      std::string TmpPathName;
246      if (D.getLTOMode() == LTOK_Full) {
247        // If we are using full LTO, then automatically create a temporary file
248        // path for the linker to use, so that it's lifetime will extend past a
249        // possible dsymutil step.
250        TmpPathName =
251            D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
252      } else if (D.getLTOMode() == LTOK_Thin)
253        // If we are using thin LTO, then create a directory instead.
254        TmpPathName = D.GetTemporaryDirectory("thinlto");
255  
256      if (!TmpPathName.empty()) {
257        auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
258        C.addTempFile(TmpPath);
259        CmdArgs.push_back("-object_path_lto");
260        CmdArgs.push_back(TmpPath);
261      }
262    }
263  
264    // Use -lto_library option to specify the libLTO.dylib path. Try to find
265    // it in clang installed libraries. ld64 will only look at this argument
266    // when it actually uses LTO, so libLTO.dylib only needs to exist at link
267    // time if ld64 decides that it needs to use LTO.
268    // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
269    // next to it. That's ok since ld64 using a libLTO.dylib not matching the
270    // clang version won't work anyways.
271    // lld is built at the same revision as clang and statically links in
272    // LLVM libraries, so it doesn't need libLTO.dylib.
273    if (Version >= VersionTuple(133) && !LinkerIsLLD) {
274      // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
275      StringRef P = llvm::sys::path::parent_path(D.Dir);
276      SmallString<128> LibLTOPath(P);
277      llvm::sys::path::append(LibLTOPath, "lib");
278      llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
279      CmdArgs.push_back("-lto_library");
280      CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
281    }
282  
283    // ld64 version 262 and above runs the deduplicate pass by default.
284    // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`
285    //        if `!shouldLinkerNotDedup()` if LinkerIsLLD here?
286    if (Version >= VersionTuple(262) &&
287        shouldLinkerNotDedup(C.getJobs().empty(), Args))
288      CmdArgs.push_back("-no_deduplicate");
289  
290    // Derived from the "link" spec.
291    Args.AddAllArgs(CmdArgs, options::OPT_static);
292    if (!Args.hasArg(options::OPT_static))
293      CmdArgs.push_back("-dynamic");
294    if (Args.hasArg(options::OPT_fgnu_runtime)) {
295      // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
296      // here. How do we wish to handle such things?
297    }
298  
299    if (!Args.hasArg(options::OPT_dynamiclib)) {
300      AddMachOArch(Args, CmdArgs);
301      // FIXME: Why do this only on this path?
302      Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
303  
304      Args.AddLastArg(CmdArgs, options::OPT_bundle);
305      Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
306      Args.AddAllArgs(CmdArgs, options::OPT_client__name);
307  
308      Arg *A;
309      if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
310          (A = Args.getLastArg(options::OPT_current__version)) ||
311          (A = Args.getLastArg(options::OPT_install__name)))
312        D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
313                                                         << "-dynamiclib";
314  
315      Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
316      Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
317      Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
318    } else {
319      CmdArgs.push_back("-dylib");
320  
321      Arg *A;
322      if ((A = Args.getLastArg(options::OPT_bundle)) ||
323          (A = Args.getLastArg(options::OPT_bundle__loader)) ||
324          (A = Args.getLastArg(options::OPT_client__name)) ||
325          (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
326          (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
327          (A = Args.getLastArg(options::OPT_private__bundle)))
328        D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
329                                                        << "-dynamiclib";
330  
331      Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
332                                "-dylib_compatibility_version");
333      Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
334                                "-dylib_current_version");
335  
336      AddMachOArch(Args, CmdArgs);
337  
338      Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
339                                "-dylib_install_name");
340    }
341  
342    Args.AddLastArg(CmdArgs, options::OPT_all__load);
343    Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
344    Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
345    if (MachOTC.isTargetIOSBased())
346      Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
347    Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
348    Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
349    Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
350    Args.AddLastArg(CmdArgs, options::OPT_dynamic);
351    Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
352    Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
353    Args.AddAllArgs(CmdArgs, options::OPT_force__load);
354    Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
355    Args.AddAllArgs(CmdArgs, options::OPT_image__base);
356    Args.AddAllArgs(CmdArgs, options::OPT_init);
357  
358    // Add the deployment target.
359    if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)
360      MachOTC.addPlatformVersionArgs(Args, CmdArgs);
361    else
362      MachOTC.addMinVersionArgs(Args, CmdArgs);
363  
364    Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
365    Args.AddLastArg(CmdArgs, options::OPT_multi__module);
366    Args.AddLastArg(CmdArgs, options::OPT_single__module);
367    Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
368    Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
369  
370    if (const Arg *A =
371            Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
372                            options::OPT_fno_pie, options::OPT_fno_PIE)) {
373      if (A->getOption().matches(options::OPT_fpie) ||
374          A->getOption().matches(options::OPT_fPIE))
375        CmdArgs.push_back("-pie");
376      else
377        CmdArgs.push_back("-no_pie");
378    }
379  
380    // for embed-bitcode, use -bitcode_bundle in linker command
381    if (C.getDriver().embedBitcodeEnabled()) {
382      // Check if the toolchain supports bitcode build flow.
383      if (MachOTC.SupportsEmbeddedBitcode()) {
384        CmdArgs.push_back("-bitcode_bundle");
385        // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.
386        if (C.getDriver().embedBitcodeMarkerOnly() &&
387            Version >= VersionTuple(278)) {
388          CmdArgs.push_back("-bitcode_process_mode");
389          CmdArgs.push_back("marker");
390        }
391      } else
392        D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
393    }
394  
395    // If GlobalISel is enabled, pass it through to LLVM.
396    if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
397                                 options::OPT_fno_global_isel)) {
398      if (A->getOption().matches(options::OPT_fglobal_isel)) {
399        CmdArgs.push_back("-mllvm");
400        CmdArgs.push_back("-global-isel");
401        // Disable abort and fall back to SDAG silently.
402        CmdArgs.push_back("-mllvm");
403        CmdArgs.push_back("-global-isel-abort=0");
404      }
405    }
406  
407    if (Args.hasArg(options::OPT_mkernel) ||
408        Args.hasArg(options::OPT_fapple_kext) ||
409        Args.hasArg(options::OPT_ffreestanding)) {
410      CmdArgs.push_back("-mllvm");
411      CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");
412    }
413  
414    Args.AddLastArg(CmdArgs, options::OPT_prebind);
415    Args.AddLastArg(CmdArgs, options::OPT_noprebind);
416    Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
417    Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
418    Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
419    Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
420    Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
421    Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
422    Args.AddAllArgs(CmdArgs, options::OPT_segprot);
423    Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
424    Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
425    Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
426    Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
427    Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
428    Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
429    Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
430  
431    // Give --sysroot= preference, over the Apple specific behavior to also use
432    // --isysroot as the syslibroot.
433    StringRef sysroot = C.getSysRoot();
434    if (sysroot != "") {
435      CmdArgs.push_back("-syslibroot");
436      CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
437    } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
438      CmdArgs.push_back("-syslibroot");
439      CmdArgs.push_back(A->getValue());
440    }
441  
442    Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
443    Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
444    Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
445    Args.AddAllArgs(CmdArgs, options::OPT_undefined);
446    Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
447    Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
448    Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
449    Args.AddAllArgs(CmdArgs, options::OPT_y);
450    Args.AddLastArg(CmdArgs, options::OPT_w);
451    Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
452    Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
453    Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
454    Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
455    Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
456    Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
457    Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
458    Args.AddLastArg(CmdArgs, options::OPT_why_load);
459    Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
460    Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
461    Args.AddLastArg(CmdArgs, options::OPT_dylinker);
462    Args.AddLastArg(CmdArgs, options::OPT_Mach);
463  
464    if (LinkerIsLLD) {
465      if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
466        SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0
467                                  ? ""
468                                  : CSPGOGenerateArg->getValue());
469        llvm::sys::path::append(Path, "default_%m.profraw");
470        CmdArgs.push_back("--cs-profile-generate");
471        CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
472      } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
473        SmallString<128> Path(
474            ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
475        if (Path.empty() || llvm::sys::fs::is_directory(Path))
476          llvm::sys::path::append(Path, "default.profdata");
477        CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
478      }
479    }
480  }
481  
482  /// Determine whether we are linking the ObjC runtime.
isObjCRuntimeLinked(const ArgList & Args)483  static bool isObjCRuntimeLinked(const ArgList &Args) {
484    if (isObjCAutoRefCount(Args)) {
485      Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
486      return true;
487    }
488    return Args.hasArg(options::OPT_fobjc_link_runtime);
489  }
490  
checkRemarksOptions(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)491  static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
492                                  const llvm::Triple &Triple) {
493    // When enabling remarks, we need to error if:
494    // * The remark file is specified but we're targeting multiple architectures,
495    // which means more than one remark file is being generated.
496    bool hasMultipleInvocations =
497        Args.getAllArgValues(options::OPT_arch).size() > 1;
498    bool hasExplicitOutputFile =
499        Args.getLastArg(options::OPT_foptimization_record_file_EQ);
500    if (hasMultipleInvocations && hasExplicitOutputFile) {
501      D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
502          << "-foptimization-record-file";
503      return false;
504    }
505    return true;
506  }
507  
renderRemarksOptions(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple,const InputInfo & Output,const JobAction & JA)508  static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
509                                   const llvm::Triple &Triple,
510                                   const InputInfo &Output, const JobAction &JA) {
511    StringRef Format = "yaml";
512    if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
513      Format = A->getValue();
514  
515    CmdArgs.push_back("-mllvm");
516    CmdArgs.push_back("-lto-pass-remarks-output");
517    CmdArgs.push_back("-mllvm");
518  
519    const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
520    if (A) {
521      CmdArgs.push_back(A->getValue());
522    } else {
523      assert(Output.isFilename() && "Unexpected ld output.");
524      SmallString<128> F;
525      F = Output.getFilename();
526      F += ".opt.";
527      F += Format;
528  
529      CmdArgs.push_back(Args.MakeArgString(F));
530    }
531  
532    if (const Arg *A =
533            Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
534      CmdArgs.push_back("-mllvm");
535      std::string Passes =
536          std::string("-lto-pass-remarks-filter=") + A->getValue();
537      CmdArgs.push_back(Args.MakeArgString(Passes));
538    }
539  
540    if (!Format.empty()) {
541      CmdArgs.push_back("-mllvm");
542      Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
543      CmdArgs.push_back(Args.MakeArgString(FormatArg));
544    }
545  
546    if (getLastProfileUseArg(Args)) {
547      CmdArgs.push_back("-mllvm");
548      CmdArgs.push_back("-lto-pass-remarks-with-hotness");
549  
550      if (const Arg *A =
551              Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
552        CmdArgs.push_back("-mllvm");
553        std::string Opt =
554            std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
555        CmdArgs.push_back(Args.MakeArgString(Opt));
556      }
557    }
558  }
559  
560  static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);
561  
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const562  void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
563                                    const InputInfo &Output,
564                                    const InputInfoList &Inputs,
565                                    const ArgList &Args,
566                                    const char *LinkingOutput) const {
567    assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
568  
569    // If the number of arguments surpasses the system limits, we will encode the
570    // input files in a separate file, shortening the command line. To this end,
571    // build a list of input file names that can be passed via a file with the
572    // -filelist linker option.
573    llvm::opt::ArgStringList InputFileList;
574  
575    // The logic here is derived from gcc's behavior; most of which
576    // comes from specs (starting with link_command). Consult gcc for
577    // more information.
578    ArgStringList CmdArgs;
579  
580    /// Hack(tm) to ignore linking errors when we are doing ARC migration.
581    if (Args.hasArg(options::OPT_ccc_arcmt_check,
582                    options::OPT_ccc_arcmt_migrate)) {
583      for (const auto &Arg : Args)
584        Arg->claim();
585      const char *Exec =
586          Args.MakeArgString(getToolChain().GetProgramPath("touch"));
587      CmdArgs.push_back(Output.getFilename());
588      C.addCommand(std::make_unique<Command>(JA, *this,
589                                             ResponseFileSupport::None(), Exec,
590                                             CmdArgs, std::nullopt, Output));
591      return;
592    }
593  
594    VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
595  
596    bool LinkerIsLLD;
597    const char *Exec =
598        Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));
599  
600    // xrOS always uses -platform-version.
601    bool UsePlatformVersion = getToolChain().getTriple().isXROS();
602  
603    // I'm not sure why this particular decomposition exists in gcc, but
604    // we follow suite for ease of comparison.
605    AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,
606                UsePlatformVersion);
607  
608    if (willEmitRemarks(Args) &&
609        checkRemarksOptions(getToolChain().getDriver(), Args,
610                            getToolChain().getTriple()))
611      renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);
612  
613    // Propagate the -moutline flag to the linker in LTO.
614    if (Arg *A =
615            Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {
616      if (A->getOption().matches(options::OPT_moutline)) {
617        if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
618          CmdArgs.push_back("-mllvm");
619          CmdArgs.push_back("-enable-machine-outliner");
620        }
621      } else {
622        // Disable all outlining behaviour if we have mno-outline. We need to do
623        // this explicitly, because targets which support default outlining will
624        // try to do work if we don't.
625        CmdArgs.push_back("-mllvm");
626        CmdArgs.push_back("-enable-machine-outliner=never");
627      }
628    }
629  
630    // Outline from linkonceodr functions by default in LTO, whenever the outliner
631    // is enabled.  Note that the target may enable the machine outliner
632    // independently of -moutline.
633    CmdArgs.push_back("-mllvm");
634    CmdArgs.push_back("-enable-linkonceodr-outlining");
635  
636    // Setup statistics file output.
637    SmallString<128> StatsFile =
638        getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
639    if (!StatsFile.empty()) {
640      CmdArgs.push_back("-mllvm");
641      CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));
642    }
643  
644    // It seems that the 'e' option is completely ignored for dynamic executables
645    // (the default), and with static executables, the last one wins, as expected.
646    Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
647                              options::OPT_Z_Flag, options::OPT_u_Group});
648  
649    // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
650    // members of static archive libraries which implement Objective-C classes or
651    // categories.
652    if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
653      CmdArgs.push_back("-ObjC");
654  
655    CmdArgs.push_back("-o");
656    CmdArgs.push_back(Output.getFilename());
657  
658    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
659      getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
660  
661    Args.AddAllArgs(CmdArgs, options::OPT_L);
662  
663    AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
664    // Build the input file for -filelist (list of linker input files) in case we
665    // need it later
666    for (const auto &II : Inputs) {
667      if (!II.isFilename()) {
668        // This is a linker input argument.
669        // We cannot mix input arguments and file names in a -filelist input, thus
670        // we prematurely stop our list (remaining files shall be passed as
671        // arguments).
672        if (InputFileList.size() > 0)
673          break;
674  
675        continue;
676      }
677  
678      InputFileList.push_back(II.getFilename());
679    }
680  
681    // Additional linker set-up and flags for Fortran. This is required in order
682    // to generate executables.
683    if (getToolChain().getDriver().IsFlangMode()) {
684      addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
685      addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
686    }
687  
688    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
689      addOpenMPRuntime(C, CmdArgs, getToolChain(), Args);
690  
691    if (isObjCRuntimeLinked(Args) &&
692        !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
693      // We use arclite library for both ARC and subscripting support.
694      getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
695  
696      CmdArgs.push_back("-framework");
697      CmdArgs.push_back("Foundation");
698      // Link libobj.
699      CmdArgs.push_back("-lobjc");
700    }
701  
702    if (LinkingOutput) {
703      CmdArgs.push_back("-arch_multiple");
704      CmdArgs.push_back("-final_output");
705      CmdArgs.push_back(LinkingOutput);
706    }
707  
708    if (Args.hasArg(options::OPT_fnested_functions))
709      CmdArgs.push_back("-allow_stack_execute");
710  
711    getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
712  
713    StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
714    if (!Parallelism.empty()) {
715      CmdArgs.push_back("-mllvm");
716      unsigned NumThreads =
717          llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
718      CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
719    }
720  
721    if (getToolChain().ShouldLinkCXXStdlib(Args))
722      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
723  
724    bool NoStdOrDefaultLibs =
725        Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
726    bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
727    if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
728      // link_ssp spec is empty.
729  
730      // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
731      // we just want to link the builtins, not the other libs like libSystem.
732      if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
733        getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");
734      } else {
735        // Let the tool chain choose which runtime library to link.
736        getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
737                                                  ForceLinkBuiltins);
738  
739        // No need to do anything for pthreads. Claim argument to avoid warning.
740        Args.ClaimAllArgs(options::OPT_pthread);
741        Args.ClaimAllArgs(options::OPT_pthreads);
742      }
743    }
744  
745    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
746      // endfile_spec is empty.
747    }
748  
749    Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
750    Args.AddAllArgs(CmdArgs, options::OPT_F);
751  
752    // -iframework should be forwarded as -F.
753    for (const Arg *A : Args.filtered(options::OPT_iframework))
754      CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
755  
756    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
757      if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
758        if (A->getValue() == StringRef("Accelerate")) {
759          CmdArgs.push_back("-framework");
760          CmdArgs.push_back("Accelerate");
761        }
762      }
763    }
764  
765    // Add non-standard, platform-specific search paths, e.g., for DriverKit:
766    //  -L<sysroot>/System/DriverKit/usr/lib
767    //  -F<sysroot>/System/DriverKit/System/Library/Framework
768    {
769      bool NonStandardSearchPath = false;
770      const auto &Triple = getToolChain().getTriple();
771      if (Triple.isDriverKit()) {
772        // ld64 fixed the implicit -F and -L paths in ld64-605.1+.
773        NonStandardSearchPath =
774            Version.getMajor() < 605 ||
775            (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);
776      }
777  
778      if (NonStandardSearchPath) {
779        if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
780          auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
781            SmallString<128> P(Sysroot->getValue());
782            AppendPlatformPrefix(P, Triple);
783            llvm::sys::path::append(P, SearchPath);
784            if (getToolChain().getVFS().exists(P)) {
785              CmdArgs.push_back(Args.MakeArgString(Flag + P));
786            }
787          };
788          AddSearchPath("-L", "/usr/lib");
789          AddSearchPath("-F", "/System/Library/Frameworks");
790        }
791      }
792    }
793  
794    ResponseFileSupport ResponseSupport;
795    if (Version >= VersionTuple(705) || LinkerIsLLD) {
796      ResponseSupport = ResponseFileSupport::AtFileUTF8();
797    } else {
798      // For older versions of the linker, use the legacy filelist method instead.
799      ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
800                         "-filelist"};
801    }
802  
803    std::unique_ptr<Command> Cmd = std::make_unique<Command>(
804        JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
805    Cmd->setInputFileList(std::move(InputFileList));
806    C.addCommand(std::move(Cmd));
807  }
808  
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const809  void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
810                                           const InputInfo &Output,
811                                           const InputInfoList &Inputs,
812                                           const ArgList &Args,
813                                           const char *LinkingOutput) const {
814    const Driver &D = getToolChain().getDriver();
815  
816    // Silence warning for "clang -g foo.o -o foo"
817    Args.ClaimAllArgs(options::OPT_g_Group);
818    // and "clang -emit-llvm foo.o -o foo"
819    Args.ClaimAllArgs(options::OPT_emit_llvm);
820    // and for "clang -w foo.o -o foo". Other warning options are already
821    // handled somewhere else.
822    Args.ClaimAllArgs(options::OPT_w);
823    // Silence warnings when linking C code with a C++ '-stdlib' argument.
824    Args.ClaimAllArgs(options::OPT_stdlib_EQ);
825  
826    // libtool <options> <output_file> <input_files>
827    ArgStringList CmdArgs;
828    // Create and insert file members with a deterministic index.
829    CmdArgs.push_back("-static");
830    CmdArgs.push_back("-D");
831    CmdArgs.push_back("-no_warning_for_no_symbols");
832    CmdArgs.push_back("-o");
833    CmdArgs.push_back(Output.getFilename());
834  
835    for (const auto &II : Inputs) {
836      if (II.isFilename()) {
837        CmdArgs.push_back(II.getFilename());
838      }
839    }
840  
841    // Delete old output archive file if it already exists before generating a new
842    // archive file.
843    const auto *OutputFileName = Output.getFilename();
844    if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
845      if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
846        D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
847        return;
848      }
849    }
850  
851    const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
852    C.addCommand(std::make_unique<Command>(JA, *this,
853                                           ResponseFileSupport::AtFileUTF8(),
854                                           Exec, CmdArgs, Inputs, Output));
855  }
856  
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const857  void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
858                                  const InputInfo &Output,
859                                  const InputInfoList &Inputs,
860                                  const ArgList &Args,
861                                  const char *LinkingOutput) const {
862    ArgStringList CmdArgs;
863  
864    CmdArgs.push_back("-create");
865    assert(Output.isFilename() && "Unexpected lipo output.");
866  
867    CmdArgs.push_back("-output");
868    CmdArgs.push_back(Output.getFilename());
869  
870    for (const auto &II : Inputs) {
871      assert(II.isFilename() && "Unexpected lipo input.");
872      CmdArgs.push_back(II.getFilename());
873    }
874  
875    const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
876    C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
877                                           Exec, CmdArgs, Inputs, Output));
878  }
879  
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const880  void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
881                                      const InputInfo &Output,
882                                      const InputInfoList &Inputs,
883                                      const ArgList &Args,
884                                      const char *LinkingOutput) const {
885    ArgStringList CmdArgs;
886  
887    CmdArgs.push_back("-o");
888    CmdArgs.push_back(Output.getFilename());
889  
890    assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
891    const InputInfo &Input = Inputs[0];
892    assert(Input.isFilename() && "Unexpected dsymutil input.");
893    CmdArgs.push_back(Input.getFilename());
894  
895    const char *Exec =
896        Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
897    C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
898                                           Exec, CmdArgs, Inputs, Output));
899  }
900  
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const901  void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
902                                         const InputInfo &Output,
903                                         const InputInfoList &Inputs,
904                                         const ArgList &Args,
905                                         const char *LinkingOutput) const {
906    ArgStringList CmdArgs;
907    CmdArgs.push_back("--verify");
908    CmdArgs.push_back("--debug-info");
909    CmdArgs.push_back("--eh-frame");
910    CmdArgs.push_back("--quiet");
911  
912    assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
913    const InputInfo &Input = Inputs[0];
914    assert(Input.isFilename() && "Unexpected verify input");
915  
916    // Grabbing the output of the earlier dsymutil run.
917    CmdArgs.push_back(Input.getFilename());
918  
919    const char *Exec =
920        Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
921    C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
922                                           Exec, CmdArgs, Inputs, Output));
923  }
924  
MachO(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)925  MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
926      : ToolChain(D, Triple, Args) {
927    // We expect 'as', 'ld', etc. to be adjacent to our install dir.
928    getProgramPaths().push_back(getDriver().Dir);
929  }
930  
931  /// Darwin - Darwin tool chain for i386 and x86_64.
Darwin(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)932  Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
933      : MachO(D, Triple, Args), TargetInitialized(false),
934        CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
935  
LookupTypeForExtension(StringRef Ext) const936  types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
937    types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
938  
939    // Darwin always preprocesses assembly files (unless -x is used explicitly).
940    if (Ty == types::TY_PP_Asm)
941      return types::TY_Asm;
942  
943    return Ty;
944  }
945  
HasNativeLLVMSupport() const946  bool MachO::HasNativeLLVMSupport() const { return true; }
947  
GetDefaultCXXStdlibType() const948  ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
949    // Always use libc++ by default
950    return ToolChain::CST_Libcxx;
951  }
952  
953  /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
getDefaultObjCRuntime(bool isNonFragile) const954  ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
955    if (isTargetWatchOSBased())
956      return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
957    if (isTargetIOSBased())
958      return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
959    if (isTargetXROS()) {
960      // XROS uses the iOS runtime.
961      auto T = llvm::Triple(Twine("arm64-apple-") +
962                            llvm::Triple::getOSTypeName(llvm::Triple::XROS) +
963                            TargetVersion.getAsString());
964      return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion());
965    }
966    if (isNonFragile)
967      return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
968    return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
969  }
970  
971  /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
hasBlocksRuntime() const972  bool Darwin::hasBlocksRuntime() const {
973    if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())
974      return true;
975    else if (isTargetIOSBased())
976      return !isIPhoneOSVersionLT(3, 2);
977    else {
978      assert(isTargetMacOSBased() && "unexpected darwin target");
979      return !isMacosxVersionLT(10, 6);
980    }
981  }
982  
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const983  void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
984                                  ArgStringList &CC1Args) const {
985    CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
986  }
987  
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const988  void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
989                                 ArgStringList &CC1Args) const {
990    RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
991  }
992  
993  // This is just a MachO name translation routine and there's no
994  // way to join this into ARMTargetParser without breaking all
995  // other assumptions. Maybe MachO should consider standardising
996  // their nomenclature.
ArmMachOArchName(StringRef Arch)997  static const char *ArmMachOArchName(StringRef Arch) {
998    return llvm::StringSwitch<const char *>(Arch)
999        .Case("armv6k", "armv6")
1000        .Case("armv6m", "armv6m")
1001        .Case("armv5tej", "armv5")
1002        .Case("xscale", "xscale")
1003        .Case("armv4t", "armv4t")
1004        .Case("armv7", "armv7")
1005        .Cases("armv7a", "armv7-a", "armv7")
1006        .Cases("armv7r", "armv7-r", "armv7")
1007        .Cases("armv7em", "armv7e-m", "armv7em")
1008        .Cases("armv7k", "armv7-k", "armv7k")
1009        .Cases("armv7m", "armv7-m", "armv7m")
1010        .Cases("armv7s", "armv7-s", "armv7s")
1011        .Default(nullptr);
1012  }
1013  
ArmMachOArchNameCPU(StringRef CPU)1014  static const char *ArmMachOArchNameCPU(StringRef CPU) {
1015    llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
1016    if (ArchKind == llvm::ARM::ArchKind::INVALID)
1017      return nullptr;
1018    StringRef Arch = llvm::ARM::getArchName(ArchKind);
1019  
1020    // FIXME: Make sure this MachO triple mangling is really necessary.
1021    // ARMv5* normalises to ARMv5.
1022    if (Arch.starts_with("armv5"))
1023      Arch = Arch.substr(0, 5);
1024    // ARMv6*, except ARMv6M, normalises to ARMv6.
1025    else if (Arch.starts_with("armv6") && !Arch.ends_with("6m"))
1026      Arch = Arch.substr(0, 5);
1027    // ARMv7A normalises to ARMv7.
1028    else if (Arch.ends_with("v7a"))
1029      Arch = Arch.substr(0, 5);
1030    return Arch.data();
1031  }
1032  
getMachOArchName(const ArgList & Args) const1033  StringRef MachO::getMachOArchName(const ArgList &Args) const {
1034    switch (getTriple().getArch()) {
1035    default:
1036      return getDefaultUniversalArchName();
1037  
1038    case llvm::Triple::aarch64_32:
1039      return "arm64_32";
1040  
1041    case llvm::Triple::aarch64: {
1042      if (getTriple().isArm64e())
1043        return "arm64e";
1044      return "arm64";
1045    }
1046  
1047    case llvm::Triple::thumb:
1048    case llvm::Triple::arm:
1049      if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
1050        if (const char *Arch = ArmMachOArchName(A->getValue()))
1051          return Arch;
1052  
1053      if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
1054        if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
1055          return Arch;
1056  
1057      return "arm";
1058    }
1059  }
1060  
getLinkerVersion(const llvm::opt::ArgList & Args) const1061  VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
1062    if (LinkerVersion) {
1063  #ifndef NDEBUG
1064      VersionTuple NewLinkerVersion;
1065      if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1066        (void)NewLinkerVersion.tryParse(A->getValue());
1067      assert(NewLinkerVersion == LinkerVersion);
1068  #endif
1069      return *LinkerVersion;
1070    }
1071  
1072    VersionTuple NewLinkerVersion;
1073    if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1074      if (NewLinkerVersion.tryParse(A->getValue()))
1075        getDriver().Diag(diag::err_drv_invalid_version_number)
1076          << A->getAsString(Args);
1077  
1078    LinkerVersion = NewLinkerVersion;
1079    return *LinkerVersion;
1080  }
1081  
~Darwin()1082  Darwin::~Darwin() {}
1083  
~MachO()1084  MachO::~MachO() {}
1085  
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const1086  std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
1087                                                  types::ID InputType) const {
1088    llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
1089  
1090    // If the target isn't initialized (e.g., an unknown Darwin platform, return
1091    // the default triple).
1092    if (!isTargetInitialized())
1093      return Triple.getTriple();
1094  
1095    SmallString<16> Str;
1096    if (isTargetWatchOSBased())
1097      Str += "watchos";
1098    else if (isTargetTvOSBased())
1099      Str += "tvos";
1100    else if (isTargetDriverKit())
1101      Str += "driverkit";
1102    else if (isTargetIOSBased() || isTargetMacCatalyst())
1103      Str += "ios";
1104    else if (isTargetXROS())
1105      Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS);
1106    else
1107      Str += "macosx";
1108    Str += getTripleTargetVersion().getAsString();
1109    Triple.setOSName(Str);
1110  
1111    return Triple.getTriple();
1112  }
1113  
getTool(Action::ActionClass AC) const1114  Tool *MachO::getTool(Action::ActionClass AC) const {
1115    switch (AC) {
1116    case Action::LipoJobClass:
1117      if (!Lipo)
1118        Lipo.reset(new tools::darwin::Lipo(*this));
1119      return Lipo.get();
1120    case Action::DsymutilJobClass:
1121      if (!Dsymutil)
1122        Dsymutil.reset(new tools::darwin::Dsymutil(*this));
1123      return Dsymutil.get();
1124    case Action::VerifyDebugInfoJobClass:
1125      if (!VerifyDebug)
1126        VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
1127      return VerifyDebug.get();
1128    default:
1129      return ToolChain::getTool(AC);
1130    }
1131  }
1132  
buildLinker() const1133  Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
1134  
buildStaticLibTool() const1135  Tool *MachO::buildStaticLibTool() const {
1136    return new tools::darwin::StaticLibTool(*this);
1137  }
1138  
buildAssembler() const1139  Tool *MachO::buildAssembler() const {
1140    return new tools::darwin::Assembler(*this);
1141  }
1142  
DarwinClang(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)1143  DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
1144                           const ArgList &Args)
1145      : Darwin(D, Triple, Args) {}
1146  
addClangWarningOptions(ArgStringList & CC1Args) const1147  void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
1148    // Always error about undefined 'TARGET_OS_*' macros.
1149    CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
1150    CC1Args.push_back("-Werror=undef-prefix");
1151  
1152    // For modern targets, promote certain warnings to errors.
1153    if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
1154      // Always enable -Wdeprecated-objc-isa-usage and promote it
1155      // to an error.
1156      CC1Args.push_back("-Wdeprecated-objc-isa-usage");
1157      CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
1158  
1159      // For iOS and watchOS, also error about implicit function declarations,
1160      // as that can impact calling conventions.
1161      if (!isTargetMacOS())
1162        CC1Args.push_back("-Werror=implicit-function-declaration");
1163    }
1164  }
1165  
1166  /// Take a path that speculatively points into Xcode and return the
1167  /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path
1168  /// otherwise.
getXcodeDeveloperPath(StringRef PathIntoXcode)1169  static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
1170    static constexpr llvm::StringLiteral XcodeAppSuffix(
1171        ".app/Contents/Developer");
1172    size_t Index = PathIntoXcode.find(XcodeAppSuffix);
1173    if (Index == StringRef::npos)
1174      return "";
1175    return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());
1176  }
1177  
AddLinkARCArgs(const ArgList & Args,ArgStringList & CmdArgs) const1178  void DarwinClang::AddLinkARCArgs(const ArgList &Args,
1179                                   ArgStringList &CmdArgs) const {
1180    // Avoid linking compatibility stubs on i386 mac.
1181    if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)
1182      return;
1183    if (isTargetAppleSiliconMac())
1184      return;
1185    // ARC runtime is supported everywhere on arm64e.
1186    if (getTriple().isArm64e())
1187      return;
1188    if (isTargetXROS())
1189      return;
1190  
1191    ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
1192  
1193    if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
1194        runtime.hasSubscripting())
1195      return;
1196  
1197    SmallString<128> P(getDriver().ClangExecutable);
1198    llvm::sys::path::remove_filename(P); // 'clang'
1199    llvm::sys::path::remove_filename(P); // 'bin'
1200    llvm::sys::path::append(P, "lib", "arc");
1201  
1202    // 'libarclite' usually lives in the same toolchain as 'clang'. However, the
1203    // Swift open source toolchains for macOS distribute Clang without libarclite.
1204    // In that case, to allow the linker to find 'libarclite', we point to the
1205    // 'libarclite' in the XcodeDefault toolchain instead.
1206    if (!getVFS().exists(P)) {
1207      auto updatePath = [&](const Arg *A) {
1208        // Try to infer the path to 'libarclite' in the toolchain from the
1209        // specified SDK path.
1210        StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
1211        if (XcodePathForSDK.empty())
1212          return false;
1213  
1214        P = XcodePathForSDK;
1215        llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
1216                                "lib", "arc");
1217        return getVFS().exists(P);
1218      };
1219  
1220      bool updated = false;
1221      if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
1222        updated = updatePath(A);
1223  
1224      if (!updated) {
1225        if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
1226          updatePath(A);
1227      }
1228    }
1229  
1230    CmdArgs.push_back("-force_load");
1231    llvm::sys::path::append(P, "libarclite_");
1232    // Mash in the platform.
1233    if (isTargetWatchOSSimulator())
1234      P += "watchsimulator";
1235    else if (isTargetWatchOS())
1236      P += "watchos";
1237    else if (isTargetTvOSSimulator())
1238      P += "appletvsimulator";
1239    else if (isTargetTvOS())
1240      P += "appletvos";
1241    else if (isTargetIOSSimulator())
1242      P += "iphonesimulator";
1243    else if (isTargetIPhoneOS())
1244      P += "iphoneos";
1245    else
1246      P += "macosx";
1247    P += ".a";
1248  
1249    if (!getVFS().exists(P))
1250      getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;
1251  
1252    CmdArgs.push_back(Args.MakeArgString(P));
1253  }
1254  
GetDefaultDwarfVersion() const1255  unsigned DarwinClang::GetDefaultDwarfVersion() const {
1256    // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
1257    if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
1258        (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
1259      return 2;
1260    // Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.
1261    if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||
1262        (isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||
1263        (isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||
1264        (isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||
1265        (isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||
1266        (isTargetMacOSBased() &&
1267         TargetVersion.empty())) // apple-darwin, no version.
1268      return 4;
1269    return 5;
1270  }
1271  
AddLinkRuntimeLib(const ArgList & Args,ArgStringList & CmdArgs,StringRef Component,RuntimeLinkOptions Opts,bool IsShared) const1272  void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
1273                                StringRef Component, RuntimeLinkOptions Opts,
1274                                bool IsShared) const {
1275    std::string P = getCompilerRT(
1276        Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static);
1277  
1278    // For now, allow missing resource libraries to support developers who may
1279    // not have compiler-rt checked out or integrated into their build (unless
1280    // we explicitly force linking with this library).
1281    if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
1282      const char *LibArg = Args.MakeArgString(P);
1283      CmdArgs.push_back(LibArg);
1284    }
1285  
1286    // Adding the rpaths might negatively interact when other rpaths are involved,
1287    // so we should make sure we add the rpaths last, after all user-specified
1288    // rpaths. This is currently true from this place, but we need to be
1289    // careful if this function is ever called before user's rpaths are emitted.
1290    if (Opts & RLO_AddRPath) {
1291      assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library");
1292  
1293      // Add @executable_path to rpath to support having the dylib copied with
1294      // the executable.
1295      CmdArgs.push_back("-rpath");
1296      CmdArgs.push_back("@executable_path");
1297  
1298      // Add the compiler-rt library's directory to rpath to support using the
1299      // dylib from the default location without copying.
1300      CmdArgs.push_back("-rpath");
1301      CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P)));
1302    }
1303  }
1304  
getCompilerRT(const ArgList &,StringRef Component,FileType Type) const1305  std::string MachO::getCompilerRT(const ArgList &, StringRef Component,
1306                                   FileType Type) const {
1307    assert(Type != ToolChain::FT_Object &&
1308           "it doesn't make sense to ask for the compiler-rt library name as an "
1309           "object file");
1310    SmallString<64> MachOLibName = StringRef("libclang_rt");
1311    // On MachO, the builtins component is not in the library name
1312    if (Component != "builtins") {
1313      MachOLibName += '.';
1314      MachOLibName += Component;
1315    }
1316    MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";
1317  
1318    SmallString<128> FullPath(getDriver().ResourceDir);
1319    llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded",
1320                            MachOLibName);
1321    return std::string(FullPath);
1322  }
1323  
getCompilerRT(const ArgList &,StringRef Component,FileType Type) const1324  std::string Darwin::getCompilerRT(const ArgList &, StringRef Component,
1325                                    FileType Type) const {
1326    assert(Type != ToolChain::FT_Object &&
1327           "it doesn't make sense to ask for the compiler-rt library name as an "
1328           "object file");
1329    SmallString<64> DarwinLibName = StringRef("libclang_rt.");
1330    // On Darwin, the builtins component is not in the library name
1331    if (Component != "builtins") {
1332      DarwinLibName += Component;
1333      DarwinLibName += '_';
1334    }
1335    DarwinLibName += getOSLibraryNameSuffix();
1336    DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";
1337  
1338    SmallString<128> FullPath(getDriver().ResourceDir);
1339    llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName);
1340    return std::string(FullPath);
1341  }
1342  
getPlatformFamily() const1343  StringRef Darwin::getPlatformFamily() const {
1344    switch (TargetPlatform) {
1345      case DarwinPlatformKind::MacOS:
1346        return "MacOSX";
1347      case DarwinPlatformKind::IPhoneOS:
1348        if (TargetEnvironment == MacCatalyst)
1349          return "MacOSX";
1350        return "iPhone";
1351      case DarwinPlatformKind::TvOS:
1352        return "AppleTV";
1353      case DarwinPlatformKind::WatchOS:
1354        return "Watch";
1355      case DarwinPlatformKind::DriverKit:
1356        return "DriverKit";
1357      case DarwinPlatformKind::XROS:
1358        return "XR";
1359    }
1360    llvm_unreachable("Unsupported platform");
1361  }
1362  
getSDKName(StringRef isysroot)1363  StringRef Darwin::getSDKName(StringRef isysroot) {
1364    // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
1365    auto BeginSDK = llvm::sys::path::rbegin(isysroot);
1366    auto EndSDK = llvm::sys::path::rend(isysroot);
1367    for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
1368      StringRef SDK = *IT;
1369      if (SDK.ends_with(".sdk"))
1370          return SDK.slice(0, SDK.size() - 4);
1371    }
1372    return "";
1373  }
1374  
getOSLibraryNameSuffix(bool IgnoreSim) const1375  StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
1376    switch (TargetPlatform) {
1377    case DarwinPlatformKind::MacOS:
1378      return "osx";
1379    case DarwinPlatformKind::IPhoneOS:
1380      if (TargetEnvironment == MacCatalyst)
1381        return "osx";
1382      return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
1383                                                                 : "iossim";
1384    case DarwinPlatformKind::TvOS:
1385      return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
1386                                                                 : "tvossim";
1387    case DarwinPlatformKind::WatchOS:
1388      return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
1389                                                                 : "watchossim";
1390    case DarwinPlatformKind::XROS:
1391      return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros"
1392                                                                 : "xrossim";
1393    case DarwinPlatformKind::DriverKit:
1394      return "driverkit";
1395    }
1396    llvm_unreachable("Unsupported platform");
1397  }
1398  
1399  /// Check if the link command contains a symbol export directive.
hasExportSymbolDirective(const ArgList & Args)1400  static bool hasExportSymbolDirective(const ArgList &Args) {
1401    for (Arg *A : Args) {
1402      if (A->getOption().matches(options::OPT_exported__symbols__list))
1403        return true;
1404      if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
1405          !A->getOption().matches(options::OPT_Xlinker))
1406        continue;
1407      if (A->containsValue("-exported_symbols_list") ||
1408          A->containsValue("-exported_symbol"))
1409        return true;
1410    }
1411    return false;
1412  }
1413  
1414  /// Add an export directive for \p Symbol to the link command.
addExportedSymbol(ArgStringList & CmdArgs,const char * Symbol)1415  static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
1416    CmdArgs.push_back("-exported_symbol");
1417    CmdArgs.push_back(Symbol);
1418  }
1419  
1420  /// Add a sectalign directive for \p Segment and \p Section to the maximum
1421  /// expected page size for Darwin.
1422  ///
1423  /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
1424  /// Use a common alignment constant (16K) for now, and reduce the alignment on
1425  /// macOS if it proves important.
addSectalignToPage(const ArgList & Args,ArgStringList & CmdArgs,StringRef Segment,StringRef Section)1426  static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
1427                                 StringRef Segment, StringRef Section) {
1428    for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
1429                          Args.MakeArgString(Section), "0x4000"})
1430      CmdArgs.push_back(A);
1431  }
1432  
addProfileRTLibs(const ArgList & Args,ArgStringList & CmdArgs) const1433  void Darwin::addProfileRTLibs(const ArgList &Args,
1434                                ArgStringList &CmdArgs) const {
1435    if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1436      return;
1437  
1438    AddLinkRuntimeLib(Args, CmdArgs, "profile",
1439                      RuntimeLinkOptions(RLO_AlwaysLink));
1440  
1441    bool ForGCOV = needsGCovInstrumentation(Args);
1442  
1443    // If we have a symbol export directive and we're linking in the profile
1444    // runtime, automatically export symbols necessary to implement some of the
1445    // runtime's functionality.
1446    if (hasExportSymbolDirective(Args) && ForGCOV) {
1447      addExportedSymbol(CmdArgs, "___gcov_dump");
1448      addExportedSymbol(CmdArgs, "___gcov_reset");
1449      addExportedSymbol(CmdArgs, "_writeout_fn_list");
1450      addExportedSymbol(CmdArgs, "_reset_fn_list");
1451    }
1452  
1453    // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page
1454    // alignment. This allows profile counters to be mmap()'d to disk. Note that
1455    // it's not enough to just page-align __llvm_prf_cnts: the following section
1456    // must also be page-aligned so that its data is not clobbered by mmap().
1457    //
1458    // The section alignment is only needed when continuous profile sync is
1459    // enabled, but this is expected to be the default in Xcode. Specifying the
1460    // extra alignment also allows the same binary to be used with/without sync
1461    // enabled.
1462    if (!ForGCOV) {
1463      for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {
1464        addSectalignToPage(
1465            Args, CmdArgs, "__DATA",
1466            llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
1467                                          /*AddSegmentInfo=*/false));
1468      }
1469    }
1470  }
1471  
AddLinkSanitizerLibArgs(const ArgList & Args,ArgStringList & CmdArgs,StringRef Sanitizer,bool Shared) const1472  void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
1473                                            ArgStringList &CmdArgs,
1474                                            StringRef Sanitizer,
1475                                            bool Shared) const {
1476    auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
1477    AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
1478  }
1479  
GetRuntimeLibType(const ArgList & Args) const1480  ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
1481      const ArgList &Args) const {
1482    if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
1483      StringRef Value = A->getValue();
1484      if (Value != "compiler-rt" && Value != "platform")
1485        getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
1486            << Value << "darwin";
1487    }
1488  
1489    return ToolChain::RLT_CompilerRT;
1490  }
1491  
AddLinkRuntimeLibArgs(const ArgList & Args,ArgStringList & CmdArgs,bool ForceLinkBuiltinRT) const1492  void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
1493                                          ArgStringList &CmdArgs,
1494                                          bool ForceLinkBuiltinRT) const {
1495    // Call once to ensure diagnostic is printed if wrong value was specified
1496    GetRuntimeLibType(Args);
1497  
1498    // Darwin doesn't support real static executables, don't link any runtime
1499    // libraries with -static.
1500    if (Args.hasArg(options::OPT_static) ||
1501        Args.hasArg(options::OPT_fapple_kext) ||
1502        Args.hasArg(options::OPT_mkernel)) {
1503      if (ForceLinkBuiltinRT)
1504        AddLinkRuntimeLib(Args, CmdArgs, "builtins");
1505      return;
1506    }
1507  
1508    // Reject -static-libgcc for now, we can deal with this when and if someone
1509    // cares. This is useful in situations where someone wants to statically link
1510    // something like libstdc++, and needs its runtime support routines.
1511    if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
1512      getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
1513      return;
1514    }
1515  
1516    const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
1517  
1518    if (!Sanitize.needsSharedRt()) {
1519      const char *sanitizer = nullptr;
1520      if (Sanitize.needsUbsanRt()) {
1521        sanitizer = "UndefinedBehaviorSanitizer";
1522      } else if (Sanitize.needsAsanRt()) {
1523        sanitizer = "AddressSanitizer";
1524      } else if (Sanitize.needsTsanRt()) {
1525        sanitizer = "ThreadSanitizer";
1526      }
1527      if (sanitizer) {
1528        getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)
1529            << sanitizer;
1530        return;
1531      }
1532    }
1533  
1534    if (Sanitize.linkRuntimes()) {
1535      if (Sanitize.needsAsanRt()) {
1536        if (Sanitize.needsStableAbi()) {
1537          AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);
1538        } else {
1539          assert(Sanitize.needsSharedRt() &&
1540                 "Static sanitizer runtimes not supported");
1541          AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
1542        }
1543      }
1544      if (Sanitize.needsLsanRt())
1545        AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
1546      if (Sanitize.needsUbsanRt()) {
1547        assert(Sanitize.needsSharedRt() &&
1548               "Static sanitizer runtimes not supported");
1549        AddLinkSanitizerLibArgs(
1550            Args, CmdArgs,
1551            Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");
1552      }
1553      if (Sanitize.needsTsanRt()) {
1554        assert(Sanitize.needsSharedRt() &&
1555               "Static sanitizer runtimes not supported");
1556        AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
1557      }
1558      if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
1559        AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
1560  
1561          // Libfuzzer is written in C++ and requires libcxx.
1562          AddCXXStdlibLibArgs(Args, CmdArgs);
1563      }
1564      if (Sanitize.needsStatsRt()) {
1565        AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
1566        AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
1567      }
1568    }
1569  
1570    const XRayArgs &XRay = getXRayArgs();
1571    if (XRay.needsXRayRt()) {
1572      AddLinkRuntimeLib(Args, CmdArgs, "xray");
1573      AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
1574      AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
1575    }
1576  
1577    if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {
1578      CmdArgs.push_back("-framework");
1579      CmdArgs.push_back("DriverKit");
1580    }
1581  
1582    // Otherwise link libSystem, then the dynamic runtime library, and finally any
1583    // target specific static runtime library.
1584    if (!isTargetDriverKit())
1585      CmdArgs.push_back("-lSystem");
1586  
1587    // Select the dynamic runtime library and the target specific static library.
1588    if (isTargetIOSBased()) {
1589      // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
1590      // it never went into the SDK.
1591      // Linking against libgcc_s.1 isn't needed for iOS 5.0+
1592      if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
1593          getTriple().getArch() != llvm::Triple::aarch64)
1594        CmdArgs.push_back("-lgcc_s.1");
1595    }
1596    AddLinkRuntimeLib(Args, CmdArgs, "builtins");
1597  }
1598  
1599  /// Returns the most appropriate macOS target version for the current process.
1600  ///
1601  /// If the macOS SDK version is the same or earlier than the system version,
1602  /// then the SDK version is returned. Otherwise the system version is returned.
getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion)1603  static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
1604    llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
1605    if (!SystemTriple.isMacOSX())
1606      return std::string(MacOSSDKVersion);
1607    VersionTuple SystemVersion;
1608    SystemTriple.getMacOSXVersion(SystemVersion);
1609  
1610    unsigned Major, Minor, Micro;
1611    bool HadExtra;
1612    if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
1613                                   HadExtra))
1614      return std::string(MacOSSDKVersion);
1615    VersionTuple SDKVersion(Major, Minor, Micro);
1616  
1617    if (SDKVersion > SystemVersion)
1618      return SystemVersion.getAsString();
1619    return std::string(MacOSSDKVersion);
1620  }
1621  
1622  namespace {
1623  
1624  /// The Darwin OS that was selected or inferred from arguments / environment.
1625  struct DarwinPlatform {
1626    enum SourceKind {
1627      /// The OS was specified using the -target argument.
1628      TargetArg,
1629      /// The OS was specified using the -mtargetos= argument.
1630      MTargetOSArg,
1631      /// The OS was specified using the -m<os>-version-min argument.
1632      OSVersionArg,
1633      /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
1634      DeploymentTargetEnv,
1635      /// The OS was inferred from the SDK.
1636      InferredFromSDK,
1637      /// The OS was inferred from the -arch.
1638      InferredFromArch
1639    };
1640  
1641    using DarwinPlatformKind = Darwin::DarwinPlatformKind;
1642    using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;
1643  
getPlatform__anon76651bdd0311::DarwinPlatform1644    DarwinPlatformKind getPlatform() const { return Platform; }
1645  
getEnvironment__anon76651bdd0311::DarwinPlatform1646    DarwinEnvironmentKind getEnvironment() const { return Environment; }
1647  
setEnvironment__anon76651bdd0311::DarwinPlatform1648    void setEnvironment(DarwinEnvironmentKind Kind) {
1649      Environment = Kind;
1650      InferSimulatorFromArch = false;
1651    }
1652  
getOSVersion__anon76651bdd0311::DarwinPlatform1653    StringRef getOSVersion() const {
1654      if (Kind == OSVersionArg)
1655        return Argument->getValue();
1656      return OSVersion;
1657    }
1658  
setOSVersion__anon76651bdd0311::DarwinPlatform1659    void setOSVersion(StringRef S) {
1660      assert(Kind == TargetArg && "Unexpected kind!");
1661      OSVersion = std::string(S);
1662    }
1663  
hasOSVersion__anon76651bdd0311::DarwinPlatform1664    bool hasOSVersion() const { return HasOSVersion; }
1665  
getNativeTargetVersion__anon76651bdd0311::DarwinPlatform1666    VersionTuple getNativeTargetVersion() const {
1667      assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
1668             "native target version is specified only for Mac Catalyst");
1669      return NativeTargetVersion;
1670    }
1671  
1672    /// Returns true if the target OS was explicitly specified.
isExplicitlySpecified__anon76651bdd0311::DarwinPlatform1673    bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
1674  
1675    /// Returns true if the simulator environment can be inferred from the arch.
canInferSimulatorFromArch__anon76651bdd0311::DarwinPlatform1676    bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
1677  
getTargetVariantTriple__anon76651bdd0311::DarwinPlatform1678    const std::optional<llvm::Triple> &getTargetVariantTriple() const {
1679      return TargetVariantTriple;
1680    }
1681  
1682    /// Adds the -m<os>-version-min argument to the compiler invocation.
addOSVersionMinArgument__anon76651bdd0311::DarwinPlatform1683    void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
1684      if (Argument)
1685        return;
1686      assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&
1687             "Invalid kind");
1688      options::ID Opt;
1689      switch (Platform) {
1690      case DarwinPlatformKind::MacOS:
1691        Opt = options::OPT_mmacos_version_min_EQ;
1692        break;
1693      case DarwinPlatformKind::IPhoneOS:
1694        Opt = options::OPT_mios_version_min_EQ;
1695        break;
1696      case DarwinPlatformKind::TvOS:
1697        Opt = options::OPT_mtvos_version_min_EQ;
1698        break;
1699      case DarwinPlatformKind::WatchOS:
1700        Opt = options::OPT_mwatchos_version_min_EQ;
1701        break;
1702      case DarwinPlatformKind::XROS:
1703        // xrOS always explicitly provides a version in the triple.
1704        return;
1705      case DarwinPlatformKind::DriverKit:
1706        // DriverKit always explicitly provides a version in the triple.
1707        return;
1708      }
1709      Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
1710      Args.append(Argument);
1711    }
1712  
1713    /// Returns the OS version with the argument / environment variable that
1714    /// specified it.
getAsString__anon76651bdd0311::DarwinPlatform1715    std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
1716      switch (Kind) {
1717      case TargetArg:
1718      case MTargetOSArg:
1719      case OSVersionArg:
1720      case InferredFromSDK:
1721      case InferredFromArch:
1722        assert(Argument && "OS version argument not yet inferred");
1723        return Argument->getAsString(Args);
1724      case DeploymentTargetEnv:
1725        return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
1726      }
1727      llvm_unreachable("Unsupported Darwin Source Kind");
1728    }
1729  
setEnvironment__anon76651bdd0311::DarwinPlatform1730    void setEnvironment(llvm::Triple::EnvironmentType EnvType,
1731                        const VersionTuple &OSVersion,
1732                        const std::optional<DarwinSDKInfo> &SDKInfo) {
1733      switch (EnvType) {
1734      case llvm::Triple::Simulator:
1735        Environment = DarwinEnvironmentKind::Simulator;
1736        break;
1737      case llvm::Triple::MacABI: {
1738        Environment = DarwinEnvironmentKind::MacCatalyst;
1739        // The minimum native macOS target for MacCatalyst is macOS 10.15.
1740        NativeTargetVersion = VersionTuple(10, 15);
1741        if (HasOSVersion && SDKInfo) {
1742          if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
1743                  DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
1744            if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
1745                    OSVersion, NativeTargetVersion, std::nullopt)) {
1746              NativeTargetVersion = *MacOSVersion;
1747            }
1748          }
1749        }
1750        // In a zippered build, we could be building for a macOS target that's
1751        // lower than the version that's implied by the OS version. In that case
1752        // we need to use the minimum version as the native target version.
1753        if (TargetVariantTriple) {
1754          auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
1755          if (TargetVariantVersion.getMajor()) {
1756            if (TargetVariantVersion < NativeTargetVersion)
1757              NativeTargetVersion = TargetVariantVersion;
1758          }
1759        }
1760        break;
1761      }
1762      default:
1763        break;
1764      }
1765    }
1766  
1767    static DarwinPlatform
createFromTarget__anon76651bdd0311::DarwinPlatform1768    createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
1769                     std::optional<llvm::Triple> TargetVariantTriple,
1770                     const std::optional<DarwinSDKInfo> &SDKInfo) {
1771      DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
1772                            A);
1773      VersionTuple OsVersion = TT.getOSVersion();
1774      if (OsVersion.getMajor() == 0)
1775        Result.HasOSVersion = false;
1776      Result.TargetVariantTriple = TargetVariantTriple;
1777      Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
1778      return Result;
1779    }
1780    static DarwinPlatform
createFromMTargetOS__anon76651bdd0311::DarwinPlatform1781    createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
1782                        llvm::Triple::EnvironmentType Environment, Arg *A,
1783                        const std::optional<DarwinSDKInfo> &SDKInfo) {
1784      DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
1785                            OSVersion.getAsString(), A);
1786      Result.InferSimulatorFromArch = false;
1787      Result.setEnvironment(Environment, OSVersion, SDKInfo);
1788      return Result;
1789    }
createOSVersionArg__anon76651bdd0311::DarwinPlatform1790    static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
1791                                             bool IsSimulator) {
1792      DarwinPlatform Result{OSVersionArg, Platform, A};
1793      if (IsSimulator)
1794        Result.Environment = DarwinEnvironmentKind::Simulator;
1795      return Result;
1796    }
createDeploymentTargetEnv__anon76651bdd0311::DarwinPlatform1797    static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
1798                                                    StringRef EnvVarName,
1799                                                    StringRef Value) {
1800      DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
1801      Result.EnvVarName = EnvVarName;
1802      return Result;
1803    }
createFromSDK__anon76651bdd0311::DarwinPlatform1804    static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
1805                                        StringRef Value,
1806                                        bool IsSimulator = false) {
1807      DarwinPlatform Result(InferredFromSDK, Platform, Value);
1808      if (IsSimulator)
1809        Result.Environment = DarwinEnvironmentKind::Simulator;
1810      Result.InferSimulatorFromArch = false;
1811      return Result;
1812    }
createFromArch__anon76651bdd0311::DarwinPlatform1813    static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
1814                                         StringRef Value) {
1815      return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
1816    }
1817  
1818    /// Constructs an inferred SDKInfo value based on the version inferred from
1819    /// the SDK path itself. Only works for values that were created by inferring
1820    /// the platform from the SDKPath.
inferSDKInfo__anon76651bdd0311::DarwinPlatform1821    DarwinSDKInfo inferSDKInfo() {
1822      assert(Kind == InferredFromSDK && "can infer SDK info only");
1823      llvm::VersionTuple Version;
1824      bool IsValid = !Version.tryParse(OSVersion);
1825      (void)IsValid;
1826      assert(IsValid && "invalid SDK version");
1827      return DarwinSDKInfo(
1828          Version,
1829          /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));
1830    }
1831  
1832  private:
DarwinPlatform__anon76651bdd0311::DarwinPlatform1833    DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
1834        : Kind(Kind), Platform(Platform), Argument(Argument) {}
DarwinPlatform__anon76651bdd0311::DarwinPlatform1835    DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
1836                   Arg *Argument = nullptr)
1837        : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
1838  
getPlatformFromOS__anon76651bdd0311::DarwinPlatform1839    static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
1840      switch (OS) {
1841      case llvm::Triple::Darwin:
1842      case llvm::Triple::MacOSX:
1843        return DarwinPlatformKind::MacOS;
1844      case llvm::Triple::IOS:
1845        return DarwinPlatformKind::IPhoneOS;
1846      case llvm::Triple::TvOS:
1847        return DarwinPlatformKind::TvOS;
1848      case llvm::Triple::WatchOS:
1849        return DarwinPlatformKind::WatchOS;
1850      case llvm::Triple::XROS:
1851        return DarwinPlatformKind::XROS;
1852      case llvm::Triple::DriverKit:
1853        return DarwinPlatformKind::DriverKit;
1854      default:
1855        llvm_unreachable("Unable to infer Darwin variant");
1856      }
1857    }
1858  
1859    SourceKind Kind;
1860    DarwinPlatformKind Platform;
1861    DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
1862    VersionTuple NativeTargetVersion;
1863    std::string OSVersion;
1864    bool HasOSVersion = true, InferSimulatorFromArch = true;
1865    Arg *Argument;
1866    StringRef EnvVarName;
1867    std::optional<llvm::Triple> TargetVariantTriple;
1868  };
1869  
1870  /// Returns the deployment target that's specified using the -m<os>-version-min
1871  /// argument.
1872  std::optional<DarwinPlatform>
getDeploymentTargetFromOSVersionArg(DerivedArgList & Args,const Driver & TheDriver)1873  getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
1874                                      const Driver &TheDriver) {
1875    Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
1876    Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
1877                                      options::OPT_mios_simulator_version_min_EQ);
1878    Arg *TvOSVersion =
1879        Args.getLastArg(options::OPT_mtvos_version_min_EQ,
1880                        options::OPT_mtvos_simulator_version_min_EQ);
1881    Arg *WatchOSVersion =
1882        Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
1883                        options::OPT_mwatchos_simulator_version_min_EQ);
1884    if (macOSVersion) {
1885      if (iOSVersion || TvOSVersion || WatchOSVersion) {
1886        TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1887            << macOSVersion->getAsString(Args)
1888            << (iOSVersion ? iOSVersion
1889                           : TvOSVersion ? TvOSVersion : WatchOSVersion)
1890                   ->getAsString(Args);
1891      }
1892      return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,
1893                                                /*IsSimulator=*/false);
1894    } else if (iOSVersion) {
1895      if (TvOSVersion || WatchOSVersion) {
1896        TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1897            << iOSVersion->getAsString(Args)
1898            << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
1899      }
1900      return DarwinPlatform::createOSVersionArg(
1901          Darwin::IPhoneOS, iOSVersion,
1902          iOSVersion->getOption().getID() ==
1903              options::OPT_mios_simulator_version_min_EQ);
1904    } else if (TvOSVersion) {
1905      if (WatchOSVersion) {
1906        TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1907            << TvOSVersion->getAsString(Args)
1908            << WatchOSVersion->getAsString(Args);
1909      }
1910      return DarwinPlatform::createOSVersionArg(
1911          Darwin::TvOS, TvOSVersion,
1912          TvOSVersion->getOption().getID() ==
1913              options::OPT_mtvos_simulator_version_min_EQ);
1914    } else if (WatchOSVersion)
1915      return DarwinPlatform::createOSVersionArg(
1916          Darwin::WatchOS, WatchOSVersion,
1917          WatchOSVersion->getOption().getID() ==
1918              options::OPT_mwatchos_simulator_version_min_EQ);
1919    return std::nullopt;
1920  }
1921  
1922  /// Returns the deployment target that's specified using the
1923  /// OS_DEPLOYMENT_TARGET environment variable.
1924  std::optional<DarwinPlatform>
getDeploymentTargetFromEnvironmentVariables(const Driver & TheDriver,const llvm::Triple & Triple)1925  getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
1926                                              const llvm::Triple &Triple) {
1927    std::string Targets[Darwin::LastDarwinPlatform + 1];
1928    const char *EnvVars[] = {
1929        "MACOSX_DEPLOYMENT_TARGET",
1930        "IPHONEOS_DEPLOYMENT_TARGET",
1931        "TVOS_DEPLOYMENT_TARGET",
1932        "WATCHOS_DEPLOYMENT_TARGET",
1933        "DRIVERKIT_DEPLOYMENT_TARGET",
1934        "XROS_DEPLOYMENT_TARGET"
1935    };
1936    static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,
1937                  "Missing platform");
1938    for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {
1939      if (char *Env = ::getenv(I.value()))
1940        Targets[I.index()] = Env;
1941    }
1942  
1943    // Allow conflicts among OSX and iOS for historical reasons, but choose the
1944    // default platform.
1945    if (!Targets[Darwin::MacOS].empty() &&
1946        (!Targets[Darwin::IPhoneOS].empty() ||
1947         !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() ||
1948         !Targets[Darwin::XROS].empty())) {
1949      if (Triple.getArch() == llvm::Triple::arm ||
1950          Triple.getArch() == llvm::Triple::aarch64 ||
1951          Triple.getArch() == llvm::Triple::thumb)
1952        Targets[Darwin::MacOS] = "";
1953      else
1954        Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
1955            Targets[Darwin::TvOS] = Targets[Darwin::XROS] = "";
1956    } else {
1957      // Don't allow conflicts in any other platform.
1958      unsigned FirstTarget = std::size(Targets);
1959      for (unsigned I = 0; I != std::size(Targets); ++I) {
1960        if (Targets[I].empty())
1961          continue;
1962        if (FirstTarget == std::size(Targets))
1963          FirstTarget = I;
1964        else
1965          TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
1966              << Targets[FirstTarget] << Targets[I];
1967      }
1968    }
1969  
1970    for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {
1971      if (!Target.value().empty())
1972        return DarwinPlatform::createDeploymentTargetEnv(
1973            (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
1974            Target.value());
1975    }
1976    return std::nullopt;
1977  }
1978  
1979  /// Returns the SDK name without the optional prefix that ends with a '.' or an
1980  /// empty string otherwise.
dropSDKNamePrefix(StringRef SDKName)1981  static StringRef dropSDKNamePrefix(StringRef SDKName) {
1982    size_t PrefixPos = SDKName.find('.');
1983    if (PrefixPos == StringRef::npos)
1984      return "";
1985    return SDKName.substr(PrefixPos + 1);
1986  }
1987  
1988  /// Tries to infer the deployment target from the SDK specified by -isysroot
1989  /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
1990  /// it's available.
1991  std::optional<DarwinPlatform>
inferDeploymentTargetFromSDK(DerivedArgList & Args,const std::optional<DarwinSDKInfo> & SDKInfo)1992  inferDeploymentTargetFromSDK(DerivedArgList &Args,
1993                               const std::optional<DarwinSDKInfo> &SDKInfo) {
1994    const Arg *A = Args.getLastArg(options::OPT_isysroot);
1995    if (!A)
1996      return std::nullopt;
1997    StringRef isysroot = A->getValue();
1998    StringRef SDK = Darwin::getSDKName(isysroot);
1999    if (!SDK.size())
2000      return std::nullopt;
2001  
2002    std::string Version;
2003    if (SDKInfo) {
2004      // Get the version from the SDKSettings.json if it's available.
2005      Version = SDKInfo->getVersion().getAsString();
2006    } else {
2007      // Slice the version number out.
2008      // Version number is between the first and the last number.
2009      size_t StartVer = SDK.find_first_of("0123456789");
2010      size_t EndVer = SDK.find_last_of("0123456789");
2011      if (StartVer != StringRef::npos && EndVer > StartVer)
2012        Version = std::string(SDK.slice(StartVer, EndVer + 1));
2013    }
2014    if (Version.empty())
2015      return std::nullopt;
2016  
2017    auto CreatePlatformFromSDKName =
2018        [&](StringRef SDK) -> std::optional<DarwinPlatform> {
2019      if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator"))
2020        return DarwinPlatform::createFromSDK(
2021            Darwin::IPhoneOS, Version,
2022            /*IsSimulator=*/SDK.starts_with("iPhoneSimulator"));
2023      else if (SDK.starts_with("MacOSX"))
2024        return DarwinPlatform::createFromSDK(Darwin::MacOS,
2025                                             getSystemOrSDKMacOSVersion(Version));
2026      else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator"))
2027        return DarwinPlatform::createFromSDK(
2028            Darwin::WatchOS, Version,
2029            /*IsSimulator=*/SDK.starts_with("WatchSimulator"));
2030      else if (SDK.starts_with("AppleTVOS") ||
2031               SDK.starts_with("AppleTVSimulator"))
2032        return DarwinPlatform::createFromSDK(
2033            Darwin::TvOS, Version,
2034            /*IsSimulator=*/SDK.starts_with("AppleTVSimulator"));
2035      else if (SDK.starts_with("XR"))
2036        return DarwinPlatform::createFromSDK(
2037            Darwin::XROS, Version,
2038            /*IsSimulator=*/SDK.contains("Simulator"));
2039      else if (SDK.starts_with("DriverKit"))
2040        return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);
2041      return std::nullopt;
2042    };
2043    if (auto Result = CreatePlatformFromSDKName(SDK))
2044      return Result;
2045    // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
2046    return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
2047  }
2048  
getOSVersion(llvm::Triple::OSType OS,const llvm::Triple & Triple,const Driver & TheDriver)2049  std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
2050                           const Driver &TheDriver) {
2051    VersionTuple OsVersion;
2052    llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
2053    switch (OS) {
2054    case llvm::Triple::Darwin:
2055    case llvm::Triple::MacOSX:
2056      // If there is no version specified on triple, and both host and target are
2057      // macos, use the host triple to infer OS version.
2058      if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
2059          !Triple.getOSMajorVersion())
2060        SystemTriple.getMacOSXVersion(OsVersion);
2061      else if (!Triple.getMacOSXVersion(OsVersion))
2062        TheDriver.Diag(diag::err_drv_invalid_darwin_version)
2063            << Triple.getOSName();
2064      break;
2065    case llvm::Triple::IOS:
2066      if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
2067        OsVersion = VersionTuple(13, 1);
2068      } else
2069        OsVersion = Triple.getiOSVersion();
2070      break;
2071    case llvm::Triple::TvOS:
2072      OsVersion = Triple.getOSVersion();
2073      break;
2074    case llvm::Triple::WatchOS:
2075      OsVersion = Triple.getWatchOSVersion();
2076      break;
2077    case llvm::Triple::XROS:
2078      OsVersion = Triple.getOSVersion();
2079      if (!OsVersion.getMajor())
2080        OsVersion = OsVersion.withMajorReplaced(1);
2081      break;
2082    case llvm::Triple::DriverKit:
2083      OsVersion = Triple.getDriverKitVersion();
2084      break;
2085    default:
2086      llvm_unreachable("Unexpected OS type");
2087      break;
2088    }
2089  
2090    std::string OSVersion;
2091    llvm::raw_string_ostream(OSVersion)
2092        << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
2093        << OsVersion.getSubminor().value_or(0);
2094    return OSVersion;
2095  }
2096  
2097  /// Tries to infer the target OS from the -arch.
2098  std::optional<DarwinPlatform>
inferDeploymentTargetFromArch(DerivedArgList & Args,const Darwin & Toolchain,const llvm::Triple & Triple,const Driver & TheDriver)2099  inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
2100                                const llvm::Triple &Triple,
2101                                const Driver &TheDriver) {
2102    llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
2103  
2104    StringRef MachOArchName = Toolchain.getMachOArchName(Args);
2105    if (MachOArchName == "arm64" || MachOArchName == "arm64e")
2106      OSTy = llvm::Triple::MacOSX;
2107    else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
2108      OSTy = llvm::Triple::IOS;
2109    else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
2110      OSTy = llvm::Triple::WatchOS;
2111    else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
2112             MachOArchName != "armv7em")
2113      OSTy = llvm::Triple::MacOSX;
2114    if (OSTy == llvm::Triple::UnknownOS)
2115      return std::nullopt;
2116    return DarwinPlatform::createFromArch(OSTy,
2117                                          getOSVersion(OSTy, Triple, TheDriver));
2118  }
2119  
2120  /// Returns the deployment target that's specified using the -target option.
getDeploymentTargetFromTargetArg(DerivedArgList & Args,const llvm::Triple & Triple,const Driver & TheDriver,const std::optional<DarwinSDKInfo> & SDKInfo)2121  std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
2122      DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
2123      const std::optional<DarwinSDKInfo> &SDKInfo) {
2124    if (!Args.hasArg(options::OPT_target))
2125      return std::nullopt;
2126    if (Triple.getOS() == llvm::Triple::Darwin ||
2127        Triple.getOS() == llvm::Triple::UnknownOS)
2128      return std::nullopt;
2129    std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
2130    std::optional<llvm::Triple> TargetVariantTriple;
2131    for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
2132      llvm::Triple TVT(A->getValue());
2133      // Find a matching <arch>-<vendor> target variant triple that can be used.
2134      if ((Triple.getArch() == llvm::Triple::aarch64 ||
2135           TVT.getArchName() == Triple.getArchName()) &&
2136          TVT.getArch() == Triple.getArch() &&
2137          TVT.getSubArch() == Triple.getSubArch() &&
2138          TVT.getVendor() == Triple.getVendor()) {
2139        if (TargetVariantTriple)
2140          continue;
2141        A->claim();
2142        // Accept a -target-variant triple when compiling code that may run on
2143        // macOS or Mac Catalyst.
2144        if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
2145             TVT.isMacCatalystEnvironment()) ||
2146            (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
2147             Triple.isMacCatalystEnvironment())) {
2148          TargetVariantTriple = TVT;
2149          continue;
2150        }
2151        TheDriver.Diag(diag::err_drv_target_variant_invalid)
2152            << A->getSpelling() << A->getValue();
2153      }
2154    }
2155    return DarwinPlatform::createFromTarget(Triple, OSVersion,
2156                                            Args.getLastArg(options::OPT_target),
2157                                            TargetVariantTriple, SDKInfo);
2158  }
2159  
2160  /// Returns the deployment target that's specified using the -mtargetos option.
getDeploymentTargetFromMTargetOSArg(DerivedArgList & Args,const Driver & TheDriver,const std::optional<DarwinSDKInfo> & SDKInfo)2161  std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
2162      DerivedArgList &Args, const Driver &TheDriver,
2163      const std::optional<DarwinSDKInfo> &SDKInfo) {
2164    auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
2165    if (!A)
2166      return std::nullopt;
2167    llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
2168    switch (TT.getOS()) {
2169    case llvm::Triple::MacOSX:
2170    case llvm::Triple::IOS:
2171    case llvm::Triple::TvOS:
2172    case llvm::Triple::WatchOS:
2173    case llvm::Triple::XROS:
2174      break;
2175    default:
2176      TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
2177          << TT.getOSName() << A->getAsString(Args);
2178      return std::nullopt;
2179    }
2180  
2181    VersionTuple Version = TT.getOSVersion();
2182    if (!Version.getMajor()) {
2183      TheDriver.Diag(diag::err_drv_invalid_version_number)
2184          << A->getAsString(Args);
2185      return std::nullopt;
2186    }
2187    return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,
2188                                               TT.getEnvironment(), A, SDKInfo);
2189  }
2190  
parseSDKSettings(llvm::vfs::FileSystem & VFS,const ArgList & Args,const Driver & TheDriver)2191  std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
2192                                                const ArgList &Args,
2193                                                const Driver &TheDriver) {
2194    const Arg *A = Args.getLastArg(options::OPT_isysroot);
2195    if (!A)
2196      return std::nullopt;
2197    StringRef isysroot = A->getValue();
2198    auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
2199    if (!SDKInfoOrErr) {
2200      llvm::consumeError(SDKInfoOrErr.takeError());
2201      TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
2202      return std::nullopt;
2203    }
2204    return *SDKInfoOrErr;
2205  }
2206  
2207  } // namespace
2208  
AddDeploymentTarget(DerivedArgList & Args) const2209  void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
2210    const OptTable &Opts = getDriver().getOpts();
2211  
2212    // Support allowing the SDKROOT environment variable used by xcrun and other
2213    // Xcode tools to define the default sysroot, by making it the default for
2214    // isysroot.
2215    if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2216      // Warn if the path does not exist.
2217      if (!getVFS().exists(A->getValue()))
2218        getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
2219    } else {
2220      if (char *env = ::getenv("SDKROOT")) {
2221        // We only use this value as the default if it is an absolute path,
2222        // exists, and it is not the root path.
2223        if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
2224            StringRef(env) != "/") {
2225          Args.append(Args.MakeSeparateArg(
2226              nullptr, Opts.getOption(options::OPT_isysroot), env));
2227        }
2228      }
2229    }
2230  
2231    // Read the SDKSettings.json file for more information, like the SDK version
2232    // that we can pass down to the compiler.
2233    SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
2234  
2235    // The OS and the version can be specified using the -target argument.
2236    std::optional<DarwinPlatform> OSTarget =
2237        getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
2238    if (OSTarget) {
2239      // Disallow mixing -target and -mtargetos=.
2240      if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
2241        std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
2242        std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
2243        getDriver().Diag(diag::err_drv_cannot_mix_options)
2244            << TargetArgStr << MTargetOSArgStr;
2245      }
2246      std::optional<DarwinPlatform> OSVersionArgTarget =
2247          getDeploymentTargetFromOSVersionArg(Args, getDriver());
2248      if (OSVersionArgTarget) {
2249        unsigned TargetMajor, TargetMinor, TargetMicro;
2250        bool TargetExtra;
2251        unsigned ArgMajor, ArgMinor, ArgMicro;
2252        bool ArgExtra;
2253        if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
2254            (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
2255                                       TargetMinor, TargetMicro, TargetExtra) &&
2256             Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
2257                                       ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
2258             (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
2259                  VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
2260              TargetExtra != ArgExtra))) {
2261          // Select the OS version from the -m<os>-version-min argument when
2262          // the -target does not include an OS version.
2263          if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
2264              !OSTarget->hasOSVersion()) {
2265            OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
2266          } else {
2267            // Warn about -m<os>-version-min that doesn't match the OS version
2268            // that's specified in the target.
2269            std::string OSVersionArg =
2270                OSVersionArgTarget->getAsString(Args, Opts);
2271            std::string TargetArg = OSTarget->getAsString(Args, Opts);
2272            getDriver().Diag(clang::diag::warn_drv_overriding_option)
2273                << OSVersionArg << TargetArg;
2274          }
2275        }
2276      }
2277    } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
2278                                                               SDKInfo))) {
2279      // The OS target can be specified using the -mtargetos= argument.
2280      // Disallow mixing -mtargetos= and -m<os>version-min=.
2281      std::optional<DarwinPlatform> OSVersionArgTarget =
2282          getDeploymentTargetFromOSVersionArg(Args, getDriver());
2283      if (OSVersionArgTarget) {
2284        std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
2285        std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);
2286        getDriver().Diag(diag::err_drv_cannot_mix_options)
2287            << MTargetOSArgStr << OSVersionArgStr;
2288      }
2289    } else {
2290      // The OS target can be specified using the -m<os>version-min argument.
2291      OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
2292      // If no deployment target was specified on the command line, check for
2293      // environment defines.
2294      if (!OSTarget) {
2295        OSTarget =
2296            getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
2297        if (OSTarget) {
2298          // Don't infer simulator from the arch when the SDK is also specified.
2299          std::optional<DarwinPlatform> SDKTarget =
2300              inferDeploymentTargetFromSDK(Args, SDKInfo);
2301          if (SDKTarget)
2302            OSTarget->setEnvironment(SDKTarget->getEnvironment());
2303        }
2304      }
2305      // If there is no command-line argument to specify the Target version and
2306      // no environment variable defined, see if we can set the default based
2307      // on -isysroot using SDKSettings.json if it exists.
2308      if (!OSTarget) {
2309        OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
2310        /// If the target was successfully constructed from the SDK path, try to
2311        /// infer the SDK info if the SDK doesn't have it.
2312        if (OSTarget && !SDKInfo)
2313          SDKInfo = OSTarget->inferSDKInfo();
2314      }
2315      // If no OS targets have been specified, try to guess platform from -target
2316      // or arch name and compute the version from the triple.
2317      if (!OSTarget)
2318        OSTarget =
2319            inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
2320    }
2321  
2322    assert(OSTarget && "Unable to infer Darwin variant");
2323    OSTarget->addOSVersionMinArgument(Args, Opts);
2324    DarwinPlatformKind Platform = OSTarget->getPlatform();
2325  
2326    unsigned Major, Minor, Micro;
2327    bool HadExtra;
2328    // The major version should not be over this number.
2329    const unsigned MajorVersionLimit = 1000;
2330    // Set the tool chain target information.
2331    if (Platform == MacOS) {
2332      if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2333                                     Micro, HadExtra) ||
2334          HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
2335          Micro >= 100)
2336        getDriver().Diag(diag::err_drv_invalid_version_number)
2337            << OSTarget->getAsString(Args, Opts);
2338    } else if (Platform == IPhoneOS) {
2339      if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2340                                     Micro, HadExtra) ||
2341          HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2342        getDriver().Diag(diag::err_drv_invalid_version_number)
2343            << OSTarget->getAsString(Args, Opts);
2344      ;
2345      if (OSTarget->getEnvironment() == MacCatalyst &&
2346          (Major < 13 || (Major == 13 && Minor < 1))) {
2347        getDriver().Diag(diag::err_drv_invalid_version_number)
2348            << OSTarget->getAsString(Args, Opts);
2349        Major = 13;
2350        Minor = 1;
2351        Micro = 0;
2352      }
2353      // For 32-bit targets, the deployment target for iOS has to be earlier than
2354      // iOS 11.
2355      if (getTriple().isArch32Bit() && Major >= 11) {
2356        // If the deployment target is explicitly specified, print a diagnostic.
2357        if (OSTarget->isExplicitlySpecified()) {
2358          if (OSTarget->getEnvironment() == MacCatalyst)
2359            getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
2360          else
2361            getDriver().Diag(diag::warn_invalid_ios_deployment_target)
2362                << OSTarget->getAsString(Args, Opts);
2363          // Otherwise, set it to 10.99.99.
2364        } else {
2365          Major = 10;
2366          Minor = 99;
2367          Micro = 99;
2368        }
2369      }
2370    } else if (Platform == TvOS) {
2371      if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2372                                     Micro, HadExtra) ||
2373          HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2374        getDriver().Diag(diag::err_drv_invalid_version_number)
2375            << OSTarget->getAsString(Args, Opts);
2376    } else if (Platform == WatchOS) {
2377      if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2378                                     Micro, HadExtra) ||
2379          HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2380        getDriver().Diag(diag::err_drv_invalid_version_number)
2381            << OSTarget->getAsString(Args, Opts);
2382    } else if (Platform == DriverKit) {
2383      if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2384                                     Micro, HadExtra) ||
2385          HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
2386          Micro >= 100)
2387        getDriver().Diag(diag::err_drv_invalid_version_number)
2388            << OSTarget->getAsString(Args, Opts);
2389    } else if (Platform == XROS) {
2390      if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2391                                     Micro, HadExtra) ||
2392          HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
2393          Micro >= 100)
2394        getDriver().Diag(diag::err_drv_invalid_version_number)
2395            << OSTarget->getAsString(Args, Opts);
2396    } else
2397      llvm_unreachable("unknown kind of Darwin platform");
2398  
2399    DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
2400    // Recognize iOS targets with an x86 architecture as the iOS simulator.
2401    if (Environment == NativeEnvironment && Platform != MacOS &&
2402        Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
2403        getTriple().isX86())
2404      Environment = Simulator;
2405  
2406    VersionTuple NativeTargetVersion;
2407    if (Environment == MacCatalyst)
2408      NativeTargetVersion = OSTarget->getNativeTargetVersion();
2409    setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
2410    TargetVariantTriple = OSTarget->getTargetVariantTriple();
2411  
2412    if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2413      StringRef SDK = getSDKName(A->getValue());
2414      if (SDK.size() > 0) {
2415        size_t StartVer = SDK.find_first_of("0123456789");
2416        StringRef SDKName = SDK.slice(0, StartVer);
2417        if (!SDKName.starts_with(getPlatformFamily()) &&
2418            !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))
2419          getDriver().Diag(diag::warn_incompatible_sysroot)
2420              << SDKName << getPlatformFamily();
2421      }
2422    }
2423  }
2424  
2425  // For certain platforms/environments almost all resources (e.g., headers) are
2426  // located in sub-directories, e.g., for DriverKit they live in
2427  // <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).
AppendPlatformPrefix(SmallString<128> & Path,const llvm::Triple & T)2428  static void AppendPlatformPrefix(SmallString<128> &Path,
2429                                   const llvm::Triple &T) {
2430    if (T.isDriverKit()) {
2431      llvm::sys::path::append(Path, "System", "DriverKit");
2432    }
2433  }
2434  
2435  // Returns the effective sysroot from either -isysroot or --sysroot, plus the
2436  // platform prefix (if any).
2437  llvm::SmallString<128>
GetEffectiveSysroot(const llvm::opt::ArgList & DriverArgs) const2438  DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2439    llvm::SmallString<128> Path("/");
2440    if (DriverArgs.hasArg(options::OPT_isysroot))
2441      Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
2442    else if (!getDriver().SysRoot.empty())
2443      Path = getDriver().SysRoot;
2444  
2445    if (hasEffectiveTriple()) {
2446      AppendPlatformPrefix(Path, getEffectiveTriple());
2447    }
2448    return Path;
2449  }
2450  
AddClangSystemIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const2451  void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2452                                              llvm::opt::ArgStringList &CC1Args) const {
2453    const Driver &D = getDriver();
2454  
2455    llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2456  
2457    bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
2458    bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
2459    bool NoBuiltinInc = DriverArgs.hasFlag(
2460        options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
2461    bool ForceBuiltinInc = DriverArgs.hasFlag(
2462        options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
2463  
2464    // Add <sysroot>/usr/local/include
2465    if (!NoStdInc && !NoStdlibInc) {
2466        SmallString<128> P(Sysroot);
2467        llvm::sys::path::append(P, "usr", "local", "include");
2468        addSystemInclude(DriverArgs, CC1Args, P);
2469    }
2470  
2471    // Add the Clang builtin headers (<resource>/include)
2472    if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
2473      SmallString<128> P(D.ResourceDir);
2474      llvm::sys::path::append(P, "include");
2475      addSystemInclude(DriverArgs, CC1Args, P);
2476    }
2477  
2478    if (NoStdInc || NoStdlibInc)
2479      return;
2480  
2481    // Check for configure-time C include directories.
2482    llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
2483    if (!CIncludeDirs.empty()) {
2484      llvm::SmallVector<llvm::StringRef, 5> dirs;
2485      CIncludeDirs.split(dirs, ":");
2486      for (llvm::StringRef dir : dirs) {
2487        llvm::StringRef Prefix =
2488            llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
2489        addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
2490      }
2491    } else {
2492      // Otherwise, add <sysroot>/usr/include.
2493      SmallString<128> P(Sysroot);
2494      llvm::sys::path::append(P, "usr", "include");
2495      addExternCSystemInclude(DriverArgs, CC1Args, P.str());
2496    }
2497  }
2498  
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,llvm::SmallString<128> Base,llvm::StringRef Version,llvm::StringRef ArchDir,llvm::StringRef BitDir) const2499  bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
2500                                                llvm::opt::ArgStringList &CC1Args,
2501                                                llvm::SmallString<128> Base,
2502                                                llvm::StringRef Version,
2503                                                llvm::StringRef ArchDir,
2504                                                llvm::StringRef BitDir) const {
2505    llvm::sys::path::append(Base, Version);
2506  
2507    // Add the base dir
2508    addSystemInclude(DriverArgs, CC1Args, Base);
2509  
2510    // Add the multilib dirs
2511    {
2512      llvm::SmallString<128> P = Base;
2513      if (!ArchDir.empty())
2514        llvm::sys::path::append(P, ArchDir);
2515      if (!BitDir.empty())
2516        llvm::sys::path::append(P, BitDir);
2517      addSystemInclude(DriverArgs, CC1Args, P);
2518    }
2519  
2520    // Add the backward dir
2521    {
2522      llvm::SmallString<128> P = Base;
2523      llvm::sys::path::append(P, "backward");
2524      addSystemInclude(DriverArgs, CC1Args, P);
2525    }
2526  
2527    return getVFS().exists(Base);
2528  }
2529  
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const2530  void DarwinClang::AddClangCXXStdlibIncludeArgs(
2531      const llvm::opt::ArgList &DriverArgs,
2532      llvm::opt::ArgStringList &CC1Args) const {
2533    // The implementation from a base class will pass through the -stdlib to
2534    // CC1Args.
2535    // FIXME: this should not be necessary, remove usages in the frontend
2536    //        (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
2537    //        Also check whether this is used for setting library search paths.
2538    ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
2539  
2540    if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
2541                          options::OPT_nostdincxx))
2542      return;
2543  
2544    llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2545  
2546    switch (GetCXXStdlibType(DriverArgs)) {
2547    case ToolChain::CST_Libcxx: {
2548      // On Darwin, libc++ can be installed in one of the following places:
2549      // 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
2550      // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
2551      //
2552      // The precedence of paths is as listed above, i.e. we take the first path
2553      // that exists. Note that we never include libc++ twice -- we take the first
2554      // path that exists and don't send the other paths to CC1 (otherwise
2555      // include_next could break).
2556  
2557      // Check for (1)
2558      // Get from '<install>/bin' to '<install>/include/c++/v1'.
2559      // Note that InstallBin can be relative, so we use '..' instead of
2560      // parent_path.
2561      llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin
2562      llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
2563      if (getVFS().exists(InstallBin)) {
2564        addSystemInclude(DriverArgs, CC1Args, InstallBin);
2565        return;
2566      } else if (DriverArgs.hasArg(options::OPT_v)) {
2567        llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
2568                     << "\"\n";
2569      }
2570  
2571      // Otherwise, check for (2)
2572      llvm::SmallString<128> SysrootUsr = Sysroot;
2573      llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
2574      if (getVFS().exists(SysrootUsr)) {
2575        addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
2576        return;
2577      } else if (DriverArgs.hasArg(options::OPT_v)) {
2578        llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
2579                     << "\"\n";
2580      }
2581  
2582      // Otherwise, don't add any path.
2583      break;
2584    }
2585  
2586    case ToolChain::CST_Libstdcxx:
2587      llvm::SmallString<128> UsrIncludeCxx = Sysroot;
2588      llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
2589  
2590      llvm::Triple::ArchType arch = getTriple().getArch();
2591      bool IsBaseFound = true;
2592      switch (arch) {
2593      default: break;
2594  
2595      case llvm::Triple::x86:
2596      case llvm::Triple::x86_64:
2597        IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2598                                                  "4.2.1",
2599                                                  "i686-apple-darwin10",
2600                                                  arch == llvm::Triple::x86_64 ? "x86_64" : "");
2601        IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2602                                                  "4.0.0", "i686-apple-darwin8",
2603                                                   "");
2604        break;
2605  
2606      case llvm::Triple::arm:
2607      case llvm::Triple::thumb:
2608        IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2609                                                  "4.2.1",
2610                                                  "arm-apple-darwin10",
2611                                                  "v7");
2612        IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2613                                                  "4.2.1",
2614                                                  "arm-apple-darwin10",
2615                                                   "v6");
2616        break;
2617  
2618      case llvm::Triple::aarch64:
2619        IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2620                                                  "4.2.1",
2621                                                  "arm64-apple-darwin10",
2622                                                  "");
2623        break;
2624      }
2625  
2626      if (!IsBaseFound) {
2627        getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2628      }
2629  
2630      break;
2631    }
2632  }
2633  
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const2634  void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
2635                                        ArgStringList &CmdArgs) const {
2636    CXXStdlibType Type = GetCXXStdlibType(Args);
2637  
2638    switch (Type) {
2639    case ToolChain::CST_Libcxx:
2640      CmdArgs.push_back("-lc++");
2641      if (Args.hasArg(options::OPT_fexperimental_library))
2642        CmdArgs.push_back("-lc++experimental");
2643      break;
2644  
2645    case ToolChain::CST_Libstdcxx:
2646      // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
2647      // it was previously found in the gcc lib dir. However, for all the Darwin
2648      // platforms we care about it was -lstdc++.6, so we search for that
2649      // explicitly if we can't see an obvious -lstdc++ candidate.
2650  
2651      // Check in the sysroot first.
2652      if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2653        SmallString<128> P(A->getValue());
2654        llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
2655  
2656        if (!getVFS().exists(P)) {
2657          llvm::sys::path::remove_filename(P);
2658          llvm::sys::path::append(P, "libstdc++.6.dylib");
2659          if (getVFS().exists(P)) {
2660            CmdArgs.push_back(Args.MakeArgString(P));
2661            return;
2662          }
2663        }
2664      }
2665  
2666      // Otherwise, look in the root.
2667      // FIXME: This should be removed someday when we don't have to care about
2668      // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
2669      if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
2670          getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
2671        CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
2672        return;
2673      }
2674  
2675      // Otherwise, let the linker search.
2676      CmdArgs.push_back("-lstdc++");
2677      break;
2678    }
2679  }
2680  
AddCCKextLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const2681  void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
2682                                     ArgStringList &CmdArgs) const {
2683    // For Darwin platforms, use the compiler-rt-based support library
2684    // instead of the gcc-provided one (which is also incidentally
2685    // only present in the gcc lib dir, which makes it hard to find).
2686  
2687    SmallString<128> P(getDriver().ResourceDir);
2688    llvm::sys::path::append(P, "lib", "darwin");
2689  
2690    // Use the newer cc_kext for iOS ARM after 6.0.
2691    if (isTargetWatchOS()) {
2692      llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
2693    } else if (isTargetTvOS()) {
2694      llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
2695    } else if (isTargetIPhoneOS()) {
2696      llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
2697    } else if (isTargetDriverKit()) {
2698      // DriverKit doesn't want extra runtime support.
2699    } else if (isTargetXROSDevice()) {
2700      llvm::sys::path::append(
2701          P, llvm::Twine("libclang_rt.cc_kext_") +
2702                 llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a");
2703    } else {
2704      llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
2705    }
2706  
2707    // For now, allow missing resource libraries to support developers who may
2708    // not have compiler-rt checked out or integrated into their build.
2709    if (getVFS().exists(P))
2710      CmdArgs.push_back(Args.MakeArgString(P));
2711  }
2712  
TranslateArgs(const DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind) const2713  DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
2714                                       StringRef BoundArch,
2715                                       Action::OffloadKind) const {
2716    DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
2717    const OptTable &Opts = getDriver().getOpts();
2718  
2719    // FIXME: We really want to get out of the tool chain level argument
2720    // translation business, as it makes the driver functionality much
2721    // more opaque. For now, we follow gcc closely solely for the
2722    // purpose of easily achieving feature parity & testability. Once we
2723    // have something that works, we should reevaluate each translation
2724    // and try to push it down into tool specific logic.
2725  
2726    for (Arg *A : Args) {
2727      if (A->getOption().matches(options::OPT_Xarch__)) {
2728        // Skip this argument unless the architecture matches either the toolchain
2729        // triple arch, or the arch being bound.
2730        StringRef XarchArch = A->getValue(0);
2731        if (!(XarchArch == getArchName() ||
2732              (!BoundArch.empty() && XarchArch == BoundArch)))
2733          continue;
2734  
2735        Arg *OriginalArg = A;
2736        TranslateXarchArgs(Args, A, DAL);
2737  
2738        // Linker input arguments require custom handling. The problem is that we
2739        // have already constructed the phase actions, so we can not treat them as
2740        // "input arguments".
2741        if (A->getOption().hasFlag(options::LinkerInput)) {
2742          // Convert the argument into individual Zlinker_input_args.
2743          for (const char *Value : A->getValues()) {
2744            DAL->AddSeparateArg(
2745                OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
2746          }
2747          continue;
2748        }
2749      }
2750  
2751      // Sob. These is strictly gcc compatible for the time being. Apple
2752      // gcc translates options twice, which means that self-expanding
2753      // options add duplicates.
2754      switch ((options::ID)A->getOption().getID()) {
2755      default:
2756        DAL->append(A);
2757        break;
2758  
2759      case options::OPT_mkernel:
2760      case options::OPT_fapple_kext:
2761        DAL->append(A);
2762        DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
2763        break;
2764  
2765      case options::OPT_dependency_file:
2766        DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
2767        break;
2768  
2769      case options::OPT_gfull:
2770        DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2771        DAL->AddFlagArg(
2772            A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
2773        break;
2774  
2775      case options::OPT_gused:
2776        DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2777        DAL->AddFlagArg(
2778            A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
2779        break;
2780  
2781      case options::OPT_shared:
2782        DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
2783        break;
2784  
2785      case options::OPT_fconstant_cfstrings:
2786        DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
2787        break;
2788  
2789      case options::OPT_fno_constant_cfstrings:
2790        DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
2791        break;
2792  
2793      case options::OPT_Wnonportable_cfstrings:
2794        DAL->AddFlagArg(A,
2795                        Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
2796        break;
2797  
2798      case options::OPT_Wno_nonportable_cfstrings:
2799        DAL->AddFlagArg(
2800            A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
2801        break;
2802      }
2803    }
2804  
2805    // Add the arch options based on the particular spelling of -arch, to match
2806    // how the driver works.
2807    if (!BoundArch.empty()) {
2808      StringRef Name = BoundArch;
2809      const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
2810      const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);
2811  
2812      // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
2813      // which defines the list of which architectures we accept.
2814      if (Name == "ppc")
2815        ;
2816      else if (Name == "ppc601")
2817        DAL->AddJoinedArg(nullptr, MCpu, "601");
2818      else if (Name == "ppc603")
2819        DAL->AddJoinedArg(nullptr, MCpu, "603");
2820      else if (Name == "ppc604")
2821        DAL->AddJoinedArg(nullptr, MCpu, "604");
2822      else if (Name == "ppc604e")
2823        DAL->AddJoinedArg(nullptr, MCpu, "604e");
2824      else if (Name == "ppc750")
2825        DAL->AddJoinedArg(nullptr, MCpu, "750");
2826      else if (Name == "ppc7400")
2827        DAL->AddJoinedArg(nullptr, MCpu, "7400");
2828      else if (Name == "ppc7450")
2829        DAL->AddJoinedArg(nullptr, MCpu, "7450");
2830      else if (Name == "ppc970")
2831        DAL->AddJoinedArg(nullptr, MCpu, "970");
2832  
2833      else if (Name == "ppc64" || Name == "ppc64le")
2834        DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2835  
2836      else if (Name == "i386")
2837        ;
2838      else if (Name == "i486")
2839        DAL->AddJoinedArg(nullptr, MArch, "i486");
2840      else if (Name == "i586")
2841        DAL->AddJoinedArg(nullptr, MArch, "i586");
2842      else if (Name == "i686")
2843        DAL->AddJoinedArg(nullptr, MArch, "i686");
2844      else if (Name == "pentium")
2845        DAL->AddJoinedArg(nullptr, MArch, "pentium");
2846      else if (Name == "pentium2")
2847        DAL->AddJoinedArg(nullptr, MArch, "pentium2");
2848      else if (Name == "pentpro")
2849        DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
2850      else if (Name == "pentIIm3")
2851        DAL->AddJoinedArg(nullptr, MArch, "pentium2");
2852  
2853      else if (Name == "x86_64" || Name == "x86_64h")
2854        DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2855  
2856      else if (Name == "arm")
2857        DAL->AddJoinedArg(nullptr, MArch, "armv4t");
2858      else if (Name == "armv4t")
2859        DAL->AddJoinedArg(nullptr, MArch, "armv4t");
2860      else if (Name == "armv5")
2861        DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
2862      else if (Name == "xscale")
2863        DAL->AddJoinedArg(nullptr, MArch, "xscale");
2864      else if (Name == "armv6")
2865        DAL->AddJoinedArg(nullptr, MArch, "armv6k");
2866      else if (Name == "armv6m")
2867        DAL->AddJoinedArg(nullptr, MArch, "armv6m");
2868      else if (Name == "armv7")
2869        DAL->AddJoinedArg(nullptr, MArch, "armv7a");
2870      else if (Name == "armv7em")
2871        DAL->AddJoinedArg(nullptr, MArch, "armv7em");
2872      else if (Name == "armv7k")
2873        DAL->AddJoinedArg(nullptr, MArch, "armv7k");
2874      else if (Name == "armv7m")
2875        DAL->AddJoinedArg(nullptr, MArch, "armv7m");
2876      else if (Name == "armv7s")
2877        DAL->AddJoinedArg(nullptr, MArch, "armv7s");
2878    }
2879  
2880    return DAL;
2881  }
2882  
AddLinkRuntimeLibArgs(const ArgList & Args,ArgStringList & CmdArgs,bool ForceLinkBuiltinRT) const2883  void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
2884                                    ArgStringList &CmdArgs,
2885                                    bool ForceLinkBuiltinRT) const {
2886    // Embedded targets are simple at the moment, not supporting sanitizers and
2887    // with different libraries for each member of the product { static, PIC } x
2888    // { hard-float, soft-float }
2889    llvm::SmallString<32> CompilerRT = StringRef("");
2890    CompilerRT +=
2891        (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
2892            ? "hard"
2893            : "soft";
2894    CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
2895  
2896    AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
2897  }
2898  
isAlignedAllocationUnavailable() const2899  bool Darwin::isAlignedAllocationUnavailable() const {
2900    llvm::Triple::OSType OS;
2901  
2902    if (isTargetMacCatalyst())
2903      return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);
2904    switch (TargetPlatform) {
2905    case MacOS: // Earlier than 10.13.
2906      OS = llvm::Triple::MacOSX;
2907      break;
2908    case IPhoneOS:
2909      OS = llvm::Triple::IOS;
2910      break;
2911    case TvOS: // Earlier than 11.0.
2912      OS = llvm::Triple::TvOS;
2913      break;
2914    case WatchOS: // Earlier than 4.0.
2915      OS = llvm::Triple::WatchOS;
2916      break;
2917    case XROS: // Always available.
2918      return false;
2919    case DriverKit: // Always available.
2920      return false;
2921    }
2922  
2923    return TargetVersion < alignedAllocMinVersion(OS);
2924  }
2925  
sdkSupportsBuiltinModules(const Darwin::DarwinPlatformKind & TargetPlatform,const Darwin::DarwinEnvironmentKind & TargetEnvironment,const std::optional<DarwinSDKInfo> & SDKInfo)2926  static bool sdkSupportsBuiltinModules(
2927      const Darwin::DarwinPlatformKind &TargetPlatform,
2928      const Darwin::DarwinEnvironmentKind &TargetEnvironment,
2929      const std::optional<DarwinSDKInfo> &SDKInfo) {
2930    if (TargetEnvironment == Darwin::NativeEnvironment ||
2931        TargetEnvironment == Darwin::Simulator ||
2932        TargetEnvironment == Darwin::MacCatalyst) {
2933      // Standard xnu/Mach/Darwin based environments
2934      // depend on the SDK version.
2935    } else {
2936      // All other environments support builtin modules from the start.
2937      return true;
2938    }
2939  
2940    if (!SDKInfo)
2941      // If there is no SDK info, assume this is building against a
2942      // pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those
2943      // don't support modules anyway, but the headers definitely
2944      // don't support builtin modules either. It might also be some
2945      // kind of degenerate build environment, err on the side of
2946      // the old behavior which is to not use builtin modules.
2947      return false;
2948  
2949    VersionTuple SDKVersion = SDKInfo->getVersion();
2950    switch (TargetPlatform) {
2951    // Existing SDKs added support for builtin modules in the fall
2952    // 2024 major releases.
2953    case Darwin::MacOS:
2954      return SDKVersion >= VersionTuple(15U);
2955    case Darwin::IPhoneOS:
2956      switch (TargetEnvironment) {
2957      case Darwin::MacCatalyst:
2958        // Mac Catalyst uses `-target arm64-apple-ios18.0-macabi` so the platform
2959        // is iOS, but it builds with the macOS SDK, so it's the macOS SDK version
2960        // that's relevant.
2961        return SDKVersion >= VersionTuple(15U);
2962      default:
2963        return SDKVersion >= VersionTuple(18U);
2964      }
2965    case Darwin::TvOS:
2966      return SDKVersion >= VersionTuple(18U);
2967    case Darwin::WatchOS:
2968      return SDKVersion >= VersionTuple(11U);
2969    case Darwin::XROS:
2970      return SDKVersion >= VersionTuple(2U);
2971  
2972    // New SDKs support builtin modules from the start.
2973    default:
2974      return true;
2975    }
2976  }
2977  
2978  static inline llvm::VersionTuple
sizedDeallocMinVersion(llvm::Triple::OSType OS)2979  sizedDeallocMinVersion(llvm::Triple::OSType OS) {
2980    switch (OS) {
2981    default:
2982      break;
2983    case llvm::Triple::Darwin:
2984    case llvm::Triple::MacOSX: // Earliest supporting version is 10.12.
2985      return llvm::VersionTuple(10U, 12U);
2986    case llvm::Triple::IOS:
2987    case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0.
2988      return llvm::VersionTuple(10U);
2989    case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0.
2990      return llvm::VersionTuple(3U);
2991    }
2992  
2993    llvm_unreachable("Unexpected OS");
2994  }
2995  
isSizedDeallocationUnavailable() const2996  bool Darwin::isSizedDeallocationUnavailable() const {
2997    llvm::Triple::OSType OS;
2998  
2999    if (isTargetMacCatalyst())
3000      return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX);
3001    switch (TargetPlatform) {
3002    case MacOS: // Earlier than 10.12.
3003      OS = llvm::Triple::MacOSX;
3004      break;
3005    case IPhoneOS:
3006      OS = llvm::Triple::IOS;
3007      break;
3008    case TvOS: // Earlier than 10.0.
3009      OS = llvm::Triple::TvOS;
3010      break;
3011    case WatchOS: // Earlier than 3.0.
3012      OS = llvm::Triple::WatchOS;
3013      break;
3014    case DriverKit:
3015    case XROS:
3016      // Always available.
3017      return false;
3018    }
3019  
3020    return TargetVersion < sizedDeallocMinVersion(OS);
3021  }
3022  
addClangTargetOptions(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadKind) const3023  void Darwin::addClangTargetOptions(
3024      const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
3025      Action::OffloadKind DeviceOffloadKind) const {
3026    // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
3027    // enabled or disabled aligned allocations.
3028    if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
3029                                  options::OPT_fno_aligned_allocation) &&
3030        isAlignedAllocationUnavailable())
3031      CC1Args.push_back("-faligned-alloc-unavailable");
3032  
3033    // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled
3034    // or disabled sized deallocations.
3035    if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,
3036                                  options::OPT_fno_sized_deallocation) &&
3037        isSizedDeallocationUnavailable())
3038      CC1Args.push_back("-fno-sized-deallocation");
3039  
3040    addClangCC1ASTargetOptions(DriverArgs, CC1Args);
3041  
3042    // Enable compatibility mode for NSItemProviderCompletionHandler in
3043    // Foundation/NSItemProvider.h.
3044    CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
3045  
3046    // Give static local variables in inline functions hidden visibility when
3047    // -fvisibility-inlines-hidden is enabled.
3048    if (!DriverArgs.getLastArgNoClaim(
3049            options::OPT_fvisibility_inlines_hidden_static_local_var,
3050            options::OPT_fno_visibility_inlines_hidden_static_local_var))
3051      CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
3052  
3053    // Earlier versions of the darwin SDK have the C standard library headers
3054    // all together in the Darwin module. That leads to module cycles with
3055    // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
3056    // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
3057    // darwin headers are in the Darwin module, there's a module cycle Darwin ->
3058    // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
3059    // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
3060    // but until then, the builtin headers need to join the system modules.
3061    // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
3062    // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
3063    // to fix the same problem with C++ headers, and is generally fragile.
3064    if (!sdkSupportsBuiltinModules(TargetPlatform, TargetEnvironment, SDKInfo))
3065      CC1Args.push_back("-fbuiltin-headers-in-system-modules");
3066  
3067    if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,
3068                                  options::OPT_fno_define_target_os_macros))
3069      CC1Args.push_back("-fdefine-target-os-macros");
3070  }
3071  
addClangCC1ASTargetOptions(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CC1ASArgs) const3072  void Darwin::addClangCC1ASTargetOptions(
3073      const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
3074    if (TargetVariantTriple) {
3075      CC1ASArgs.push_back("-darwin-target-variant-triple");
3076      CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));
3077    }
3078  
3079    if (SDKInfo) {
3080      /// Pass the SDK version to the compiler when the SDK information is
3081      /// available.
3082      auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
3083        std::string Arg;
3084        llvm::raw_string_ostream OS(Arg);
3085        OS << "-target-sdk-version=" << V;
3086        CC1ASArgs.push_back(Args.MakeArgString(Arg));
3087      };
3088  
3089      if (isTargetMacCatalyst()) {
3090        if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
3091                DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3092          std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
3093              SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
3094              std::nullopt);
3095          EmitTargetSDKVersionArg(
3096              SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
3097        }
3098      } else {
3099        EmitTargetSDKVersionArg(SDKInfo->getVersion());
3100      }
3101  
3102      /// Pass the target variant SDK version to the compiler when the SDK
3103      /// information is available and is required for target variant.
3104      if (TargetVariantTriple) {
3105        if (isTargetMacCatalyst()) {
3106          std::string Arg;
3107          llvm::raw_string_ostream OS(Arg);
3108          OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
3109          CC1ASArgs.push_back(Args.MakeArgString(Arg));
3110        } else if (const auto *MacOStoMacCatalystMapping =
3111                       SDKInfo->getVersionMapping(
3112                           DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3113          if (std::optional<VersionTuple> SDKVersion =
3114                  MacOStoMacCatalystMapping->map(
3115                      SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
3116                      std::nullopt)) {
3117            std::string Arg;
3118            llvm::raw_string_ostream OS(Arg);
3119            OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
3120            CC1ASArgs.push_back(Args.MakeArgString(Arg));
3121          }
3122        }
3123      }
3124    }
3125  }
3126  
3127  DerivedArgList *
TranslateArgs(const DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind DeviceOffloadKind) const3128  Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
3129                        Action::OffloadKind DeviceOffloadKind) const {
3130    // First get the generic Apple args, before moving onto Darwin-specific ones.
3131    DerivedArgList *DAL =
3132        MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
3133  
3134    // If no architecture is bound, none of the translations here are relevant.
3135    if (BoundArch.empty())
3136      return DAL;
3137  
3138    // Add an explicit version min argument for the deployment target. We do this
3139    // after argument translation because -Xarch_ arguments may add a version min
3140    // argument.
3141    AddDeploymentTarget(*DAL);
3142  
3143    // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
3144    // FIXME: It would be far better to avoid inserting those -static arguments,
3145    // but we can't check the deployment target in the translation code until
3146    // it is set here.
3147    if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||
3148        (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
3149      for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
3150        Arg *A = *it;
3151        ++it;
3152        if (A->getOption().getID() != options::OPT_mkernel &&
3153            A->getOption().getID() != options::OPT_fapple_kext)
3154          continue;
3155        assert(it != ie && "unexpected argument translation");
3156        A = *it;
3157        assert(A->getOption().getID() == options::OPT_static &&
3158               "missing expected -static argument");
3159        *it = nullptr;
3160        ++it;
3161      }
3162    }
3163  
3164    auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
3165    if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
3166      if (Args.hasFlag(options::OPT_fomit_frame_pointer,
3167                       options::OPT_fno_omit_frame_pointer, false))
3168        getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
3169            << "-fomit-frame-pointer" << BoundArch;
3170    }
3171  
3172    return DAL;
3173  }
3174  
getDefaultUnwindTableLevel(const ArgList & Args) const3175  ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
3176    // Unwind tables are not emitted if -fno-exceptions is supplied (except when
3177    // targeting x86_64).
3178    if (getArch() == llvm::Triple::x86_64 ||
3179        (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
3180         Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
3181                      true)))
3182      return (getArch() == llvm::Triple::aarch64 ||
3183              getArch() == llvm::Triple::aarch64_32)
3184                 ? UnwindTableLevel::Synchronous
3185                 : UnwindTableLevel::Asynchronous;
3186  
3187    return UnwindTableLevel::None;
3188  }
3189  
UseDwarfDebugFlags() const3190  bool MachO::UseDwarfDebugFlags() const {
3191    if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
3192      return S[0] != '\0';
3193    return false;
3194  }
3195  
GetGlobalDebugPathRemapping() const3196  std::string MachO::GetGlobalDebugPathRemapping() const {
3197    if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))
3198      return S;
3199    return {};
3200  }
3201  
GetExceptionModel(const ArgList & Args) const3202  llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
3203    // Darwin uses SjLj exceptions on ARM.
3204    if (getTriple().getArch() != llvm::Triple::arm &&
3205        getTriple().getArch() != llvm::Triple::thumb)
3206      return llvm::ExceptionHandling::None;
3207  
3208    // Only watchOS uses the new DWARF/Compact unwinding method.
3209    llvm::Triple Triple(ComputeLLVMTriple(Args));
3210    if (Triple.isWatchABI())
3211      return llvm::ExceptionHandling::DwarfCFI;
3212  
3213    return llvm::ExceptionHandling::SjLj;
3214  }
3215  
SupportsEmbeddedBitcode() const3216  bool Darwin::SupportsEmbeddedBitcode() const {
3217    assert(TargetInitialized && "Target not initialized!");
3218    if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
3219      return false;
3220    return true;
3221  }
3222  
isPICDefault() const3223  bool MachO::isPICDefault() const { return true; }
3224  
isPIEDefault(const llvm::opt::ArgList & Args) const3225  bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
3226  
isPICDefaultForced() const3227  bool MachO::isPICDefaultForced() const {
3228    return (getArch() == llvm::Triple::x86_64 ||
3229            getArch() == llvm::Triple::aarch64);
3230  }
3231  
SupportsProfiling() const3232  bool MachO::SupportsProfiling() const {
3233    // Profiling instrumentation is only supported on x86.
3234    return getTriple().isX86();
3235  }
3236  
addMinVersionArgs(const ArgList & Args,ArgStringList & CmdArgs) const3237  void Darwin::addMinVersionArgs(const ArgList &Args,
3238                                 ArgStringList &CmdArgs) const {
3239    VersionTuple TargetVersion = getTripleTargetVersion();
3240  
3241    assert(!isTargetXROS() && "xrOS always uses -platform-version");
3242  
3243    if (isTargetWatchOS())
3244      CmdArgs.push_back("-watchos_version_min");
3245    else if (isTargetWatchOSSimulator())
3246      CmdArgs.push_back("-watchos_simulator_version_min");
3247    else if (isTargetTvOS())
3248      CmdArgs.push_back("-tvos_version_min");
3249    else if (isTargetTvOSSimulator())
3250      CmdArgs.push_back("-tvos_simulator_version_min");
3251    else if (isTargetDriverKit())
3252      CmdArgs.push_back("-driverkit_version_min");
3253    else if (isTargetIOSSimulator())
3254      CmdArgs.push_back("-ios_simulator_version_min");
3255    else if (isTargetIOSBased())
3256      CmdArgs.push_back("-iphoneos_version_min");
3257    else if (isTargetMacCatalyst())
3258      CmdArgs.push_back("-maccatalyst_version_min");
3259    else {
3260      assert(isTargetMacOS() && "unexpected target");
3261      CmdArgs.push_back("-macosx_version_min");
3262    }
3263  
3264    VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
3265    if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3266      TargetVersion = MinTgtVers;
3267    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3268    if (TargetVariantTriple) {
3269      assert(isTargetMacOSBased() && "unexpected target");
3270      VersionTuple VariantTargetVersion;
3271      if (TargetVariantTriple->isMacOSX()) {
3272        CmdArgs.push_back("-macosx_version_min");
3273        TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);
3274      } else {
3275        assert(TargetVariantTriple->isiOS() &&
3276               TargetVariantTriple->isMacCatalystEnvironment() &&
3277               "unexpected target variant triple");
3278        CmdArgs.push_back("-maccatalyst_version_min");
3279        VariantTargetVersion = TargetVariantTriple->getiOSVersion();
3280      }
3281      VersionTuple MinTgtVers =
3282          TargetVariantTriple->getMinimumSupportedOSVersion();
3283      if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
3284        VariantTargetVersion = MinTgtVers;
3285      CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));
3286    }
3287  }
3288  
getPlatformName(Darwin::DarwinPlatformKind Platform,Darwin::DarwinEnvironmentKind Environment)3289  static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
3290                                     Darwin::DarwinEnvironmentKind Environment) {
3291    switch (Platform) {
3292    case Darwin::MacOS:
3293      return "macos";
3294    case Darwin::IPhoneOS:
3295      if (Environment == Darwin::MacCatalyst)
3296        return "mac catalyst";
3297      return "ios";
3298    case Darwin::TvOS:
3299      return "tvos";
3300    case Darwin::WatchOS:
3301      return "watchos";
3302    case Darwin::XROS:
3303      return "xros";
3304    case Darwin::DriverKit:
3305      return "driverkit";
3306    }
3307    llvm_unreachable("invalid platform");
3308  }
3309  
addPlatformVersionArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const3310  void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
3311                                      llvm::opt::ArgStringList &CmdArgs) const {
3312    auto EmitPlatformVersionArg =
3313        [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
3314            Darwin::DarwinEnvironmentKind TargetEnvironment,
3315            const llvm::Triple &TT) {
3316          // -platform_version <platform> <target_version> <sdk_version>
3317          // Both the target and SDK version support only up to 3 components.
3318          CmdArgs.push_back("-platform_version");
3319          std::string PlatformName =
3320              getPlatformName(TargetPlatform, TargetEnvironment);
3321          if (TargetEnvironment == Darwin::Simulator)
3322            PlatformName += "-simulator";
3323          CmdArgs.push_back(Args.MakeArgString(PlatformName));
3324          VersionTuple TargetVersion = TV.withoutBuild();
3325          if ((TargetPlatform == Darwin::IPhoneOS ||
3326               TargetPlatform == Darwin::TvOS) &&
3327              getTriple().getArchName() == "arm64e" &&
3328              TargetVersion.getMajor() < 14) {
3329            // arm64e slice is supported on iOS/tvOS 14+ only.
3330            TargetVersion = VersionTuple(14, 0);
3331          }
3332          VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
3333          if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3334            TargetVersion = MinTgtVers;
3335          CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3336  
3337          if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
3338            // Mac Catalyst programs must use the appropriate iOS SDK version
3339            // that corresponds to the macOS SDK version used for the compilation.
3340            std::optional<VersionTuple> iOSSDKVersion;
3341            if (SDKInfo) {
3342              if (const auto *MacOStoMacCatalystMapping =
3343                      SDKInfo->getVersionMapping(
3344                          DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3345                iOSSDKVersion = MacOStoMacCatalystMapping->map(
3346                    SDKInfo->getVersion().withoutBuild(),
3347                    minimumMacCatalystDeploymentTarget(), std::nullopt);
3348              }
3349            }
3350            CmdArgs.push_back(Args.MakeArgString(
3351                (iOSSDKVersion ? *iOSSDKVersion
3352                               : minimumMacCatalystDeploymentTarget())
3353                    .getAsString()));
3354            return;
3355          }
3356  
3357          if (SDKInfo) {
3358            VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
3359            if (!SDKVersion.getMinor())
3360              SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
3361            CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
3362          } else {
3363            // Use an SDK version that's matching the deployment target if the SDK
3364            // version is missing. This is preferred over an empty SDK version
3365            // (0.0.0) as the system's runtime might expect the linked binary to
3366            // contain a valid SDK version in order for the binary to work
3367            // correctly. It's reasonable to use the deployment target version as
3368            // a proxy for the SDK version because older SDKs don't guarantee
3369            // support for deployment targets newer than the SDK versions, so that
3370            // rules out using some predetermined older SDK version, which leaves
3371            // the deployment target version as the only reasonable choice.
3372            CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3373          }
3374        };
3375    EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
3376                           TargetEnvironment, getEffectiveTriple());
3377    if (!TargetVariantTriple)
3378      return;
3379    Darwin::DarwinPlatformKind Platform;
3380    Darwin::DarwinEnvironmentKind Environment;
3381    VersionTuple TargetVariantVersion;
3382    if (TargetVariantTriple->isMacOSX()) {
3383      TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);
3384      Platform = Darwin::MacOS;
3385      Environment = Darwin::NativeEnvironment;
3386    } else {
3387      assert(TargetVariantTriple->isiOS() &&
3388             TargetVariantTriple->isMacCatalystEnvironment() &&
3389             "unexpected target variant triple");
3390      TargetVariantVersion = TargetVariantTriple->getiOSVersion();
3391      Platform = Darwin::IPhoneOS;
3392      Environment = Darwin::MacCatalyst;
3393    }
3394    EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
3395                           *TargetVariantTriple);
3396  }
3397  
3398  // Add additional link args for the -dynamiclib option.
addDynamicLibLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)3399  static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
3400                                    ArgStringList &CmdArgs) {
3401    // Derived from darwin_dylib1 spec.
3402    if (D.isTargetIPhoneOS()) {
3403      if (D.isIPhoneOSVersionLT(3, 1))
3404        CmdArgs.push_back("-ldylib1.o");
3405      return;
3406    }
3407  
3408    if (!D.isTargetMacOS())
3409      return;
3410    if (D.isMacosxVersionLT(10, 5))
3411      CmdArgs.push_back("-ldylib1.o");
3412    else if (D.isMacosxVersionLT(10, 6))
3413      CmdArgs.push_back("-ldylib1.10.5.o");
3414  }
3415  
3416  // Add additional link args for the -bundle option.
addBundleLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)3417  static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
3418                                ArgStringList &CmdArgs) {
3419    if (Args.hasArg(options::OPT_static))
3420      return;
3421    // Derived from darwin_bundle1 spec.
3422    if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
3423        (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
3424      CmdArgs.push_back("-lbundle1.o");
3425  }
3426  
3427  // Add additional link args for the -pg option.
addPgProfilingLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)3428  static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
3429                                     ArgStringList &CmdArgs) {
3430    if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
3431      if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
3432          Args.hasArg(options::OPT_preload)) {
3433        CmdArgs.push_back("-lgcrt0.o");
3434      } else {
3435        CmdArgs.push_back("-lgcrt1.o");
3436  
3437        // darwin_crt2 spec is empty.
3438      }
3439      // By default on OS X 10.8 and later, we don't link with a crt1.o
3440      // file and the linker knows to use _main as the entry point.  But,
3441      // when compiling with -pg, we need to link with the gcrt1.o file,
3442      // so pass the -no_new_main option to tell the linker to use the
3443      // "start" symbol as the entry point.
3444      if (!D.isMacosxVersionLT(10, 8))
3445        CmdArgs.push_back("-no_new_main");
3446    } else {
3447      D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
3448          << D.isTargetMacOSBased();
3449    }
3450  }
3451  
addDefaultCRTLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)3452  static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
3453                                    ArgStringList &CmdArgs) {
3454    // Derived from darwin_crt1 spec.
3455    if (D.isTargetIPhoneOS()) {
3456      if (D.getArch() == llvm::Triple::aarch64)
3457        ; // iOS does not need any crt1 files for arm64
3458      else if (D.isIPhoneOSVersionLT(3, 1))
3459        CmdArgs.push_back("-lcrt1.o");
3460      else if (D.isIPhoneOSVersionLT(6, 0))
3461        CmdArgs.push_back("-lcrt1.3.1.o");
3462      return;
3463    }
3464  
3465    if (!D.isTargetMacOS())
3466      return;
3467    if (D.isMacosxVersionLT(10, 5))
3468      CmdArgs.push_back("-lcrt1.o");
3469    else if (D.isMacosxVersionLT(10, 6))
3470      CmdArgs.push_back("-lcrt1.10.5.o");
3471    else if (D.isMacosxVersionLT(10, 8))
3472      CmdArgs.push_back("-lcrt1.10.6.o");
3473    // darwin_crt2 spec is empty.
3474  }
3475  
addStartObjectFileArgs(const ArgList & Args,ArgStringList & CmdArgs) const3476  void Darwin::addStartObjectFileArgs(const ArgList &Args,
3477                                      ArgStringList &CmdArgs) const {
3478    // Derived from startfile spec.
3479    if (Args.hasArg(options::OPT_dynamiclib))
3480      addDynamicLibLinkArgs(*this, Args, CmdArgs);
3481    else if (Args.hasArg(options::OPT_bundle))
3482      addBundleLinkArgs(*this, Args, CmdArgs);
3483    else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
3484      addPgProfilingLinkArgs(*this, Args, CmdArgs);
3485    else if (Args.hasArg(options::OPT_static) ||
3486             Args.hasArg(options::OPT_object) ||
3487             Args.hasArg(options::OPT_preload))
3488      CmdArgs.push_back("-lcrt0.o");
3489    else
3490      addDefaultCRTLinkArgs(*this, Args, CmdArgs);
3491  
3492    if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
3493        isMacosxVersionLT(10, 5)) {
3494      const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
3495      CmdArgs.push_back(Str);
3496    }
3497  }
3498  
CheckObjCARC() const3499  void Darwin::CheckObjCARC() const {
3500    if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||
3501        (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
3502      return;
3503    getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
3504  }
3505  
getSupportedSanitizers() const3506  SanitizerMask Darwin::getSupportedSanitizers() const {
3507    const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
3508    const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
3509    SanitizerMask Res = ToolChain::getSupportedSanitizers();
3510    Res |= SanitizerKind::Address;
3511    Res |= SanitizerKind::PointerCompare;
3512    Res |= SanitizerKind::PointerSubtract;
3513    Res |= SanitizerKind::Leak;
3514    Res |= SanitizerKind::Fuzzer;
3515    Res |= SanitizerKind::FuzzerNoLink;
3516    Res |= SanitizerKind::ObjCCast;
3517  
3518    // Prior to 10.9, macOS shipped a version of the C++ standard library without
3519    // C++11 support. The same is true of iOS prior to version 5. These OS'es are
3520    // incompatible with -fsanitize=vptr.
3521    if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&
3522        !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
3523      Res |= SanitizerKind::Vptr;
3524  
3525    if ((IsX86_64 || IsAArch64) &&
3526        (isTargetMacOSBased() || isTargetIOSSimulator() ||
3527         isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
3528      Res |= SanitizerKind::Thread;
3529    }
3530  
3531    if (IsX86_64)
3532      Res |= SanitizerKind::NumericalStability;
3533  
3534    return Res;
3535  }
3536  
printVerboseInfo(raw_ostream & OS) const3537  void Darwin::printVerboseInfo(raw_ostream &OS) const {
3538    CudaInstallation->print(OS);
3539    RocmInstallation->print(OS);
3540  }
3541