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