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