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