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