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