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