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