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
30using namespace clang::driver;
31using namespace clang::driver::tools;
32using namespace clang::driver::toolchains;
33using namespace clang;
34using namespace llvm::opt;
35
36static VersionTuple minimumMacCatalystDeploymentTarget() {
37 return VersionTuple(13, 1);
38}
39
40llvm::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(S0: "i386", S1: "i486", S2: "i486SX", S3: "i586", S4: "i686", Value: llvm::Triple::x86)
55 .Cases(S0: "pentium", S1: "pentpro", S2: "pentIIm3", S3: "pentIIm5", S4: "pentium4",
56 Value: llvm::Triple::x86)
57 .Cases(S0: "x86_64", S1: "x86_64h", Value: llvm::Triple::x86_64)
58 // This is derived from the driver.
59 .Cases(S0: "arm", S1: "armv4t", S2: "armv5", S3: "armv6", S4: "armv6m", Value: llvm::Triple::arm)
60 .Cases(S0: "armv7", S1: "armv7em", S2: "armv7k", S3: "armv7m", Value: llvm::Triple::arm)
61 .Cases(S0: "armv7s", S1: "xscale", Value: llvm::Triple::arm)
62 .Cases(S0: "arm64", S1: "arm64e", Value: llvm::Triple::aarch64)
63 .Case(S: "arm64_32", Value: llvm::Triple::aarch64_32)
64 .Case(S: "r600", Value: llvm::Triple::r600)
65 .Case(S: "amdgcn", Value: llvm::Triple::amdgcn)
66 .Case(S: "nvptx", Value: llvm::Triple::nvptx)
67 .Case(S: "nvptx64", Value: llvm::Triple::nvptx64)
68 .Case(S: "amdil", Value: llvm::Triple::amdil)
69 .Case(S: "spir", Value: llvm::Triple::spir)
70 .Default(Value: llvm::Triple::UnknownArch);
71}
72
73void 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(Arch: Str);
77 T.setArch(Kind: 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(Ids: options::OPT_mios_version_min_EQ))
87 A->ignoreTargetSpecific();
88 if (T.getOS() == llvm::Triple::WatchOS)
89 for (Arg *A : Args.filtered(Ids: options::OPT_mwatchos_version_min_EQ))
90 A->ignoreTargetSpecific();
91 if (T.getOS() == llvm::Triple::TvOS)
92 for (Arg *A : Args.filtered(Ids: 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
100void 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(Ids: options::OPT_fno_integrated_as)) {
125 if (!(T.isMacOSX() && T.isMacOSXVersionLT(Major: 10, Minor: 7)))
126 CmdArgs.push_back(Elt: "-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(Ids: options::OPT_gstabs))
133 CmdArgs.push_back(Elt: "--gstabs");
134 else if (Args.hasArg(Ids: options::OPT_g_Group))
135 CmdArgs.push_back(Elt: "-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(Ids: options::OPT_force__cpusubtype__ALL))
143 CmdArgs.push_back(Elt: "-force_cpusubtype_ALL");
144
145 if (getToolChain().getArch() != llvm::Triple::x86_64 &&
146 (((Args.hasArg(Ids: options::OPT_mkernel) ||
147 Args.hasArg(Ids: options::OPT_fapple_kext)) &&
148 getMachOToolChain().isKernelStatic()) ||
149 Args.hasArg(Ids: options::OPT_static)))
150 CmdArgs.push_back(Elt: "-static");
151
152 Args.AddAllArgValues(Output&: CmdArgs, Id0: options::OPT_Wa_COMMA, Id1: options::OPT_Xassembler);
153
154 assert(Output.isFilename() && "Unexpected lipo output.");
155 CmdArgs.push_back(Elt: "-o");
156 CmdArgs.push_back(Elt: Output.getFilename());
157
158 assert(Input.isFilename() && "Invalid input.");
159 CmdArgs.push_back(Elt: Input.getFilename());
160
161 // asm_final spec is empty.
162
163 const char *Exec = Args.MakeArgString(Str: getToolChain().GetProgramPath(Name: "as"));
164 C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, args: ResponseFileSupport::None(),
165 args&: Exec, args&: CmdArgs, args: Inputs, args: Output));
166}
167
168void darwin::MachOTool::anchor() {}
169
170void 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(Elt: "-arch");
176 CmdArgs.push_back(Elt: Args.MakeArgString(Str: ArchName));
177
178 // FIXME: Is this needed anymore?
179 if (ArchName == "arm")
180 CmdArgs.push_back(Elt: "-force_cpusubtype_ALL");
181}
182
183bool 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)
201static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
202 if (Arg *A = Args.getLastArg(Ids: options::OPT_O_Group)) {
203 if (A->getOption().matches(ID: options::OPT_O0))
204 return true;
205 if (A->getOption().matches(ID: options::OPT_O))
206 return llvm::StringSwitch<bool>(A->getValue())
207 .Case(S: "1", Value: true)
208 .Default(Value: 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
217void 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(Ids: options::OPT_Z_Xlinker__no_demangle))
229 CmdArgs.push_back(Elt: "-demangle");
230
231 if (Args.hasArg(Ids: options::OPT_rdynamic) &&
232 (Version >= VersionTuple(137) || LinkerIsLLD))
233 CmdArgs.push_back(Elt: "-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(Pos: options::OPT_fapplication_extension,
238 Neg: options::OPT_fno_application_extension, Default: false))
239 CmdArgs.push_back(Elt: "-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(Prefix: "cc", Suffix: types::getTypeTempSuffix(Id: 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(Prefix: "thinlto");
253
254 if (!TmpPathName.empty()) {
255 auto *TmpPath = C.getArgs().MakeArgString(Str: TmpPathName);
256 C.addTempFile(Name: TmpPath);
257 CmdArgs.push_back(Elt: "-object_path_lto");
258 CmdArgs.push_back(Elt: 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(path: D.Dir);
274 SmallString<128> LibLTOPath(P);
275 llvm::sys::path::append(path&: LibLTOPath, a: "lib");
276 llvm::sys::path::append(path&: LibLTOPath, a: "libLTO.dylib");
277 CmdArgs.push_back(Elt: "-lto_library");
278 CmdArgs.push_back(Elt: C.getArgs().MakeArgString(Str: 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(IsLinkerOnlyAction: C.getJobs().empty(), Args))
286 CmdArgs.push_back(Elt: "-no_deduplicate");
287
288 // Derived from the "link" spec.
289 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_static);
290 if (!Args.hasArg(Ids: options::OPT_static))
291 CmdArgs.push_back(Elt: "-dynamic");
292 if (Args.hasArg(Ids: 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(Ids: options::OPT_dynamiclib)) {
298 AddMachOArch(Args, CmdArgs);
299 // FIXME: Why do this only on this path?
300 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_force__cpusubtype__ALL);
301
302 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_bundle);
303 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_bundle__loader);
304 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_client__name);
305
306 Arg *A;
307 if ((A = Args.getLastArg(Ids: options::OPT_compatibility__version)) ||
308 (A = Args.getLastArg(Ids: options::OPT_current__version)) ||
309 (A = Args.getLastArg(Ids: options::OPT_install__name)))
310 D.Diag(DiagID: diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
311 << "-dynamiclib";
312
313 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_force__flat__namespace);
314 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_keep__private__externs);
315 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_private__bundle);
316 } else {
317 CmdArgs.push_back(Elt: "-dylib");
318
319 Arg *A;
320 if ((A = Args.getLastArg(Ids: options::OPT_bundle)) ||
321 (A = Args.getLastArg(Ids: options::OPT_bundle__loader)) ||
322 (A = Args.getLastArg(Ids: options::OPT_client__name)) ||
323 (A = Args.getLastArg(Ids: options::OPT_force__flat__namespace)) ||
324 (A = Args.getLastArg(Ids: options::OPT_keep__private__externs)) ||
325 (A = Args.getLastArg(Ids: options::OPT_private__bundle)))
326 D.Diag(DiagID: diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
327 << "-dynamiclib";
328
329 Args.AddAllArgsTranslated(Output&: CmdArgs, Id0: options::OPT_compatibility__version,
330 Translation: "-dylib_compatibility_version");
331 Args.AddAllArgsTranslated(Output&: CmdArgs, Id0: options::OPT_current__version,
332 Translation: "-dylib_current_version");
333
334 AddMachOArch(Args, CmdArgs);
335
336 Args.AddAllArgsTranslated(Output&: CmdArgs, Id0: options::OPT_install__name,
337 Translation: "-dylib_install_name");
338 }
339
340 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_all__load);
341 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_allowable__client);
342 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_bind__at__load);
343 if (MachOTC.isTargetIOSBased())
344 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_arch__errors__fatal);
345 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_dead__strip);
346 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_no__dead__strip__inits__and__terms);
347 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_dylib__file);
348 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_dynamic);
349 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_exported__symbols__list);
350 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_flat__namespace);
351 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_force__load);
352 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_headerpad__max__install__names);
353 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_image__base);
354 Args.AddAllArgs(Output&: CmdArgs, Id0: 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(Output&: CmdArgs, Ids: options::OPT_nomultidefs);
363 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_multi__module);
364 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_single__module);
365 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_multiply__defined);
366 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_multiply__defined__unused);
367
368 if (const Arg *A =
369 Args.getLastArg(Ids: options::OPT_fpie, Ids: options::OPT_fPIE,
370 Ids: options::OPT_fno_pie, Ids: options::OPT_fno_PIE)) {
371 if (A->getOption().matches(ID: options::OPT_fpie) ||
372 A->getOption().matches(ID: options::OPT_fPIE))
373 CmdArgs.push_back(Elt: "-pie");
374 else
375 CmdArgs.push_back(Elt: "-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(Elt: "-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(Elt: "-bitcode_process_mode");
387 CmdArgs.push_back(Elt: "marker");
388 }
389 } else
390 D.Diag(DiagID: 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(Ids: options::OPT_fglobal_isel,
395 Ids: options::OPT_fno_global_isel)) {
396 if (A->getOption().matches(ID: options::OPT_fglobal_isel)) {
397 CmdArgs.push_back(Elt: "-mllvm");
398 CmdArgs.push_back(Elt: "-global-isel");
399 // Disable abort and fall back to SDAG silently.
400 CmdArgs.push_back(Elt: "-mllvm");
401 CmdArgs.push_back(Elt: "-global-isel-abort=0");
402 }
403 }
404
405 if (Args.hasArg(Ids: options::OPT_mkernel) ||
406 Args.hasArg(Ids: options::OPT_fapple_kext) ||
407 Args.hasArg(Ids: options::OPT_ffreestanding)) {
408 CmdArgs.push_back(Elt: "-mllvm");
409 CmdArgs.push_back(Elt: "-disable-atexit-based-global-dtor-lowering");
410 }
411
412 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_prebind);
413 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_noprebind);
414 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_nofixprebinding);
415 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_prebind__all__twolevel__modules);
416 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_read__only__relocs);
417 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_sectcreate);
418 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_sectorder);
419 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_seg1addr);
420 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_segprot);
421 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_segaddr);
422 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_segs__read__only__addr);
423 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_segs__read__write__addr);
424 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_seg__addr__table);
425 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_seg__addr__table__filename);
426 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_sub__library);
427 Args.AddAllArgs(Output&: CmdArgs, Id0: 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(Ids: options::OPT__sysroot_EQ)) {
434 CmdArgs.push_back(Elt: "-syslibroot");
435 CmdArgs.push_back(Elt: A->getValue());
436 } else if (const Arg *A = Args.getLastArg(Ids: options::OPT_isysroot)) {
437 CmdArgs.push_back(Elt: "-syslibroot");
438 CmdArgs.push_back(Elt: A->getValue());
439 } else if (StringRef sysroot = C.getSysRoot(); sysroot != "") {
440 CmdArgs.push_back(Elt: "-syslibroot");
441 CmdArgs.push_back(Elt: C.getArgs().MakeArgString(Str: sysroot));
442 }
443
444 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_twolevel__namespace);
445 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_twolevel__namespace__hints);
446 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_umbrella);
447 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_undefined);
448 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_unexported__symbols__list);
449 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_weak__reference__mismatches);
450 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_X_Flag);
451 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_y);
452 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_w);
453 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_pagezero__size);
454 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_segs__read__);
455 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_seglinkedit);
456 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_noseglinkedit);
457 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_sectalign);
458 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_sectobjectsymbols);
459 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_segcreate);
460 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_why_load);
461 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_whatsloaded);
462 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_dylinker__install__name);
463 Args.AddLastArg(Output&: CmdArgs, Ids: options::OPT_dylinker);
464 Args.AddLastArg(Output&: CmdArgs, Ids: 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&: Path, a: "default_%m.profraw");
472 CmdArgs.push_back(Elt: "--cs-profile-generate");
473 CmdArgs.push_back(Elt: Args.MakeArgString(Str: 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&: Path, a: "default.profdata");
479 CmdArgs.push_back(Elt: Args.MakeArgString(Str: Twine("--cs-profile-path=") + Path));
480 }
481
482 auto *CodeGenDataGenArg =
483 Args.getLastArg(Ids: options::OPT_fcodegen_data_generate_EQ);
484 if (CodeGenDataGenArg)
485 CmdArgs.push_back(
486 Elt: Args.MakeArgString(Str: Twine("--codegen-data-generate-path=") +
487 CodeGenDataGenArg->getValue()));
488 }
489}
490
491/// Determine whether we are linking the ObjC runtime.
492static bool isObjCRuntimeLinked(const ArgList &Args) {
493 if (isObjCAutoRefCount(Args)) {
494 Args.ClaimAllArgs(Id0: options::OPT_fobjc_link_runtime);
495 return true;
496 }
497 return Args.hasArg(Ids: options::OPT_fobjc_link_runtime);
498}
499
500static 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(Id: options::OPT_arch).size() > 1;
507 bool hasExplicitOutputFile =
508 Args.getLastArg(Ids: options::OPT_foptimization_record_file_EQ);
509 if (hasMultipleInvocations && hasExplicitOutputFile) {
510 D.Diag(DiagID: diag::err_drv_invalid_output_with_multiple_archs)
511 << "-foptimization-record-file";
512 return false;
513 }
514 return true;
515}
516
517static 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(Ids: options::OPT_fsave_optimization_record_EQ))
522 Format = A->getValue();
523
524 CmdArgs.push_back(Elt: "-mllvm");
525 CmdArgs.push_back(Elt: "-lto-pass-remarks-output");
526 CmdArgs.push_back(Elt: "-mllvm");
527
528 const Arg *A = Args.getLastArg(Ids: options::OPT_foptimization_record_file_EQ);
529 if (A) {
530 CmdArgs.push_back(Elt: 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(Elt: Args.MakeArgString(Str: F));
539 }
540
541 if (const Arg *A =
542 Args.getLastArg(Ids: options::OPT_foptimization_record_passes_EQ)) {
543 CmdArgs.push_back(Elt: "-mllvm");
544 std::string Passes =
545 std::string("-lto-pass-remarks-filter=") + A->getValue();
546 CmdArgs.push_back(Elt: Args.MakeArgString(Str: Passes));
547 }
548
549 if (!Format.empty()) {
550 CmdArgs.push_back(Elt: "-mllvm");
551 Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
552 CmdArgs.push_back(Elt: Args.MakeArgString(Str: FormatArg));
553 }
554
555 if (getLastProfileUseArg(Args)) {
556 CmdArgs.push_back(Elt: "-mllvm");
557 CmdArgs.push_back(Elt: "-lto-pass-remarks-with-hotness");
558
559 if (const Arg *A =
560 Args.getLastArg(Ids: options::OPT_fdiagnostics_hotness_threshold_EQ)) {
561 CmdArgs.push_back(Elt: "-mllvm");
562 std::string Opt =
563 std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
564 CmdArgs.push_back(Elt: Args.MakeArgString(Str: Opt));
565 }
566 }
567}
568
569static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);
570
571void 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(Str: getToolChain().GetLinkerPath(LinkerIsLLD: &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(D: getToolChain().getDriver(), Args,
605 Triple: getToolChain().getTriple()))
606 renderRemarksOptions(Args, CmdArgs, Triple: getToolChain().getTriple(), Output, JA);
607
608 // Propagate the -moutline flag to the linker in LTO.
609 if (Arg *A =
610 Args.getLastArg(Ids: options::OPT_moutline, Ids: options::OPT_mno_outline)) {
611 if (A->getOption().matches(ID: options::OPT_moutline)) {
612 if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
613 CmdArgs.push_back(Elt: "-mllvm");
614 CmdArgs.push_back(Elt: "-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(Elt: "-mllvm");
621 CmdArgs.push_back(Elt: "-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(Elt: "-mllvm");
629 CmdArgs.push_back(Elt: "-enable-linkonceodr-outlining");
630
631 // Propagate codegen data flags to the linker for the LLVM backend.
632 auto *CodeGenDataGenArg =
633 Args.getLastArg(Ids: options::OPT_fcodegen_data_generate_EQ);
634 auto *CodeGenDataUseArg = Args.getLastArg(Ids: 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(DiagID: 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(Elt: "-mllvm");
647 CmdArgs.push_back(Elt: "-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(Elt: "-mllvm");
653 CmdArgs.push_back(Elt: Args.MakeArgString(Str: Twine("-codegen-data-use-path=") +
654 CodeGenDataUseArg->getValue()));
655 }
656
657 // Setup statistics file output.
658 SmallString<128> StatsFile =
659 getStatsFileName(Args, Output, Input: Inputs[0], D: getToolChain().getDriver());
660 if (!StatsFile.empty()) {
661 CmdArgs.push_back(Elt: "-mllvm");
662 CmdArgs.push_back(Elt: Args.MakeArgString(Str: "-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(Output&: CmdArgs, Ids: {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(Ids: options::OPT_ObjC) || Args.hasArg(Ids: options::OPT_ObjCXX))
674 CmdArgs.push_back(Elt: "-ObjC");
675
676 CmdArgs.push_back(Elt: "-o");
677 CmdArgs.push_back(Elt: Output.getFilename());
678
679 if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nostartfiles))
680 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
681
682 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_L);
683
684 AddLinkerInputs(TC: 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(Elt: 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(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs)) {
706 getToolChain().addFortranRuntimeLibraryPath(Args, CmdArgs);
707 getToolChain().addFortranRuntimeLibs(Args, CmdArgs);
708 }
709
710 if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs))
711 addOpenMPRuntime(C, CmdArgs, TC: getToolChain(), Args);
712
713 if (isObjCRuntimeLinked(Args) &&
714 !Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs)) {
715 // We use arclite library for both ARC and subscripting support.
716 getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
717
718 CmdArgs.push_back(Elt: "-framework");
719 CmdArgs.push_back(Elt: "Foundation");
720 // Link libobj.
721 CmdArgs.push_back(Elt: "-lobjc");
722 }
723
724 if (LinkingOutput) {
725 CmdArgs.push_back(Elt: "-arch_multiple");
726 CmdArgs.push_back(Elt: "-final_output");
727 CmdArgs.push_back(Elt: LinkingOutput);
728 }
729
730 if (Args.hasArg(Ids: options::OPT_fnested_functions))
731 CmdArgs.push_back(Elt: "-allow_stack_execute");
732
733 getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
734
735 StringRef Parallelism = getLTOParallelism(Args, D: getToolChain().getDriver());
736 if (!Parallelism.empty()) {
737 CmdArgs.push_back(Elt: "-mllvm");
738 unsigned NumThreads =
739 llvm::get_threadpool_strategy(Num: Parallelism)->compute_thread_count();
740 CmdArgs.push_back(Elt: Args.MakeArgString(Str: "-threads=" + Twine(NumThreads)));
741 }
742
743 if (getToolChain().ShouldLinkCXXStdlib(Args))
744 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
745
746 bool NoStdOrDefaultLibs =
747 Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs);
748 bool ForceLinkBuiltins = Args.hasArg(Ids: 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, Component: "builtins");
756 } else {
757 // Let the tool chain choose which runtime library to link.
758 getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
759 ForceLinkBuiltinRT: ForceLinkBuiltins);
760
761 // No need to do anything for pthreads. Claim argument to avoid warning.
762 Args.ClaimAllArgs(Id0: options::OPT_pthread);
763 Args.ClaimAllArgs(Id0: options::OPT_pthreads);
764 }
765 }
766
767 if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nostartfiles)) {
768 // endfile_spec is empty.
769 }
770
771 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_T_Group);
772 Args.AddAllArgs(Output&: CmdArgs, Id0: options::OPT_F);
773
774 // -iframework should be forwarded as -F.
775 for (const Arg *A : Args.filtered(Ids: options::OPT_iframework))
776 CmdArgs.push_back(Elt: Args.MakeArgString(Str: std::string("-F") + A->getValue()));
777
778 if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs)) {
779 if (Arg *A = Args.getLastArg(Ids: options::OPT_fveclib)) {
780 if (A->getValue() == StringRef("Accelerate")) {
781 CmdArgs.push_back(Elt: "-framework");
782 CmdArgs.push_back(Elt: "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(u: 0) < 1);
798 }
799
800 if (NonStandardSearchPath) {
801 if (auto *Sysroot = Args.getLastArg(Ids: options::OPT_isysroot)) {
802 auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
803 SmallString<128> P(Sysroot->getValue());
804 AppendPlatformPrefix(Path&: P, T: Triple);
805 llvm::sys::path::append(path&: P, a: SearchPath);
806 if (getToolChain().getVFS().exists(Path: P)) {
807 CmdArgs.push_back(Elt: Args.MakeArgString(Str: 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 = {.ResponseKind: ResponseFileSupport::RF_FileList, .ResponseEncoding: llvm::sys::WEM_UTF8,
822 .ResponseFlag: "-filelist"};
823 }
824
825 std::unique_ptr<Command> Cmd = std::make_unique<Command>(
826 args: JA, args: *this, args&: ResponseSupport, args&: Exec, args&: CmdArgs, args: Inputs, args: Output);
827 Cmd->setInputFileList(std::move(InputFileList));
828 C.addCommand(C: std::move(Cmd));
829}
830
831void 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(Id0: options::OPT_g_Group);
840 // and "clang -emit-llvm foo.o -o foo"
841 Args.ClaimAllArgs(Id0: 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(Id0: options::OPT_w);
845 // Silence warnings when linking C code with a C++ '-stdlib' argument.
846 Args.ClaimAllArgs(Id0: 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(Elt: "-static");
852 CmdArgs.push_back(Elt: "-D");
853 CmdArgs.push_back(Elt: "-no_warning_for_no_symbols");
854 CmdArgs.push_back(Elt: "-o");
855 CmdArgs.push_back(Elt: Output.getFilename());
856
857 for (const auto &II : Inputs) {
858 if (II.isFilename()) {
859 CmdArgs.push_back(Elt: 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(Path: OutputFileName)) {
867 if (std::error_code EC = llvm::sys::fs::remove(path: OutputFileName)) {
868 D.Diag(DiagID: diag::err_drv_unable_to_remove_file) << EC.message();
869 return;
870 }
871 }
872
873 const char *Exec = Args.MakeArgString(Str: getToolChain().GetStaticLibToolPath());
874 C.addCommand(C: std::make_unique<Command>(args: JA, args: *this,
875 args: ResponseFileSupport::AtFileUTF8(),
876 args&: Exec, args&: CmdArgs, args: Inputs, args: Output));
877}
878
879void 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(Elt: "-create");
887 assert(Output.isFilename() && "Unexpected lipo output.");
888
889 CmdArgs.push_back(Elt: "-output");
890 CmdArgs.push_back(Elt: Output.getFilename());
891
892 for (const auto &II : Inputs) {
893 assert(II.isFilename() && "Unexpected lipo input.");
894 CmdArgs.push_back(Elt: II.getFilename());
895 }
896
897 StringRef LipoName = Args.getLastArgValue(Id: options::OPT_fuse_lipo_EQ, Default: "lipo");
898 const char *Exec =
899 Args.MakeArgString(Str: getToolChain().GetProgramPath(Name: LipoName.data()));
900 C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, args: ResponseFileSupport::None(),
901 args&: Exec, args&: CmdArgs, args: Inputs, args: Output));
902}
903
904void 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(Elt: "-o");
912 CmdArgs.push_back(Elt: 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(Elt: Input.getFilename());
918
919 const char *Exec =
920 Args.MakeArgString(Str: getToolChain().GetProgramPath(Name: "dsymutil"));
921 C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, args: ResponseFileSupport::None(),
922 args&: Exec, args&: CmdArgs, args: Inputs, args: Output));
923}
924
925void 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(Elt: "--verify");
932 CmdArgs.push_back(Elt: "--debug-info");
933 CmdArgs.push_back(Elt: "--eh-frame");
934 CmdArgs.push_back(Elt: "--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(Elt: Input.getFilename());
942
943 const char *Exec =
944 Args.MakeArgString(Str: getToolChain().GetProgramPath(Name: "dwarfdump"));
945 C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, args: ResponseFileSupport::None(),
946 args&: Exec, args&: CmdArgs, args: Inputs, args: Output));
947}
948
949MachO::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(Elt: getDriver().Dir);
953}
954
955AppleMachO::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.
961Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
962 : AppleMachO(D, Triple, Args), TargetInitialized(false) {}
963
964types::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
974bool MachO::HasNativeLLVMSupport() const { return true; }
975
976ToolChain::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.
982ObjCRuntime 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(Kind: 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.
1000bool Darwin::hasBlocksRuntime() const {
1001 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())
1002 return true;
1003 else if (isTargetIOSBased())
1004 return !isIPhoneOSVersionLT(V0: 3, V1: 2);
1005 else {
1006 assert(isTargetMacOSBased() && "unexpected darwin target");
1007 return !isMacosxVersionLT(V0: 10, V1: 6);
1008 }
1009}
1010
1011void AppleMachO::AddCudaIncludeArgs(const ArgList &DriverArgs,
1012 ArgStringList &CC1Args) const {
1013 CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
1014}
1015
1016void AppleMachO::AddHIPIncludeArgs(const ArgList &DriverArgs,
1017 ArgStringList &CC1Args) const {
1018 RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
1019}
1020
1021void 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.
1030static const char *ArmMachOArchName(StringRef Arch) {
1031 return llvm::StringSwitch<const char *>(Arch)
1032 .Case(S: "armv6k", Value: "armv6")
1033 .Case(S: "armv6m", Value: "armv6m")
1034 .Case(S: "armv5tej", Value: "armv5")
1035 .Case(S: "xscale", Value: "xscale")
1036 .Case(S: "armv4t", Value: "armv4t")
1037 .Case(S: "armv7", Value: "armv7")
1038 .Cases(S0: "armv7a", S1: "armv7-a", Value: "armv7")
1039 .Cases(S0: "armv7r", S1: "armv7-r", Value: "armv7")
1040 .Cases(S0: "armv7em", S1: "armv7e-m", Value: "armv7em")
1041 .Cases(S0: "armv7k", S1: "armv7-k", Value: "armv7k")
1042 .Cases(S0: "armv7m", S1: "armv7-m", Value: "armv7m")
1043 .Cases(S0: "armv7s", S1: "armv7-s", Value: "armv7s")
1044 .Default(Value: nullptr);
1045}
1046
1047static 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(AK: ArchKind);
1052
1053 // FIXME: Make sure this MachO triple mangling is really necessary.
1054 // ARMv5* normalises to ARMv5.
1055 if (Arch.starts_with(Prefix: "armv5"))
1056 Arch = Arch.substr(Start: 0, N: 5);
1057 // ARMv6*, except ARMv6M, normalises to ARMv6.
1058 else if (Arch.starts_with(Prefix: "armv6") && !Arch.ends_with(Suffix: "6m"))
1059 Arch = Arch.substr(Start: 0, N: 5);
1060 // ARMv7A normalises to ARMv7.
1061 else if (Arch.ends_with(Suffix: "v7a"))
1062 Arch = Arch.substr(Start: 0, N: 5);
1063 return Arch.data();
1064}
1065
1066StringRef 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(Ids: clang::driver::options::OPT_march_EQ))
1083 if (const char *Arch = ArmMachOArchName(Arch: A->getValue()))
1084 return Arch;
1085
1086 if (const Arg *A = Args.getLastArg(Ids: options::OPT_mcpu_EQ))
1087 if (const char *Arch = ArmMachOArchNameCPU(CPU: A->getValue()))
1088 return Arch;
1089
1090 return "arm";
1091 }
1092}
1093
1094VersionTuple 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(Ids: options::OPT_mlinker_version_EQ))
1107 if (NewLinkerVersion.tryParse(string: A->getValue()))
1108 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
1109 << A->getAsString(Args);
1110
1111 LinkerVersion = NewLinkerVersion;
1112 return *LinkerVersion;
1113}
1114
1115Darwin::~Darwin() {}
1116
1117AppleMachO::~AppleMachO() {}
1118
1119MachO::~MachO() {}
1120
1121std::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(Kind: llvm::Triple::XROS);
1141 else
1142 Str += "macosx";
1143 Str += getTripleTargetVersion().getAsString();
1144 Triple.setOSName(Str);
1145
1146 return Triple.getTriple();
1147}
1148
1149Tool *MachO::getTool(Action::ActionClass AC) const {
1150 switch (AC) {
1151 case Action::LipoJobClass:
1152 if (!Lipo)
1153 Lipo.reset(p: new tools::darwin::Lipo(*this));
1154 return Lipo.get();
1155 case Action::DsymutilJobClass:
1156 if (!Dsymutil)
1157 Dsymutil.reset(p: new tools::darwin::Dsymutil(*this));
1158 return Dsymutil.get();
1159 case Action::VerifyDebugInfoJobClass:
1160 if (!VerifyDebug)
1161 VerifyDebug.reset(p: new tools::darwin::VerifyDebug(*this));
1162 return VerifyDebug.get();
1163 default:
1164 return ToolChain::getTool(AC);
1165 }
1166}
1167
1168Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
1169
1170Tool *MachO::buildStaticLibTool() const {
1171 return new tools::darwin::StaticLibTool(*this);
1172}
1173
1174Tool *MachO::buildAssembler() const {
1175 return new tools::darwin::Assembler(*this);
1176}
1177
1178DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
1179 const ArgList &Args)
1180 : Darwin(D, Triple, Args) {}
1181
1182void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
1183 // Always error about undefined 'TARGET_OS_*' macros.
1184 CC1Args.push_back(Elt: "-Wundef-prefix=TARGET_OS_");
1185 CC1Args.push_back(Elt: "-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(Elt: "-Wdeprecated-objc-isa-usage");
1192 CC1Args.push_back(Elt: "-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(Elt: "-Werror=implicit-function-declaration");
1198 }
1199}
1200
1201void 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.
1211static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
1212 static constexpr llvm::StringLiteral XcodeAppSuffix(
1213 ".app/Contents/Developer");
1214 size_t Index = PathIntoXcode.find(Str: XcodeAppSuffix);
1215 if (Index == StringRef::npos)
1216 return "";
1217 return PathIntoXcode.take_front(N: Index + XcodeAppSuffix.size());
1218}
1219
1220void 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*/ isNonFragile: 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(path&: P); // 'clang'
1241 llvm::sys::path::remove_filename(path&: P); // 'bin'
1242 llvm::sys::path::append(path&: P, a: "lib", b: "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(Path: 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(PathIntoXcode: A->getValue());
1253 if (XcodePathForSDK.empty())
1254 return false;
1255
1256 P = XcodePathForSDK;
1257 llvm::sys::path::append(path&: P, a: "Toolchains/XcodeDefault.xctoolchain/usr",
1258 b: "lib", c: "arc");
1259 return getVFS().exists(Path: P);
1260 };
1261
1262 bool updated = false;
1263 if (const Arg *A = Args.getLastArg(Ids: options::OPT_isysroot))
1264 updated = updatePath(A);
1265
1266 if (!updated) {
1267 if (const Arg *A = Args.getLastArg(Ids: options::OPT__sysroot_EQ))
1268 updatePath(A);
1269 }
1270 }
1271
1272 CmdArgs.push_back(Elt: "-force_load");
1273 llvm::sys::path::append(path&: P, a: "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(Path: P))
1292 getDriver().Diag(DiagID: clang::diag::err_drv_darwin_sdk_missing_arclite) << P;
1293
1294 CmdArgs.push_back(Elt: Args.MakeArgString(Str: P));
1295}
1296
1297unsigned DarwinClang::GetDefaultDwarfVersion() const {
1298 // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
1299 if ((isTargetMacOSBased() && isMacosxVersionLT(V0: 10, V1: 11)) ||
1300 (isTargetIOSBased() && isIPhoneOSVersionLT(V0: 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(V0: 15)) ||
1304 (isTargetIOSBased() && isIPhoneOSVersionLT(V0: 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
1314void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
1315 StringRef Component, RuntimeLinkOptions Opts,
1316 bool IsShared) const {
1317 std::string P = getCompilerRT(
1318 Args, Component, Type: 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(Path: P)) {
1324 const char *LibArg = Args.MakeArgString(Str: P);
1325 CmdArgs.push_back(Elt: 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(Elt: "-rpath");
1338 CmdArgs.push_back(Elt: "@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(Elt: "-rpath");
1343 CmdArgs.push_back(Elt: Args.MakeArgString(Str: llvm::sys::path::parent_path(path: P)));
1344 }
1345}
1346
1347std::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(path&: FullPath, a: "lib", b: "darwin", c: "macho_embedded",
1362 d: MachOLibName);
1363 return std::string(FullPath);
1364}
1365
1366std::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(path&: FullPath, a: "lib", b: "darwin", c: DarwinLibName);
1382 return std::string(FullPath);
1383}
1384
1385StringRef 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
1405StringRef Darwin::getSDKName(StringRef isysroot) {
1406 // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
1407 auto BeginSDK = llvm::sys::path::rbegin(path: isysroot);
1408 auto EndSDK = llvm::sys::path::rend(path: isysroot);
1409 for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
1410 StringRef SDK = *IT;
1411 if (SDK.consume_back(Suffix: ".sdk"))
1412 return SDK;
1413 }
1414 return "";
1415}
1416
1417StringRef 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.
1442static bool hasExportSymbolDirective(const ArgList &Args) {
1443 for (Arg *A : Args) {
1444 if (A->getOption().matches(ID: options::OPT_exported__symbols__list))
1445 return true;
1446 if (!A->getOption().matches(ID: options::OPT_Wl_COMMA) &&
1447 !A->getOption().matches(ID: options::OPT_Xlinker))
1448 continue;
1449 if (A->containsValue(Value: "-exported_symbols_list") ||
1450 A->containsValue(Value: "-exported_symbol"))
1451 return true;
1452 }
1453 return false;
1454}
1455
1456/// Add an export directive for \p Symbol to the link command.
1457static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
1458 CmdArgs.push_back(Elt: "-exported_symbol");
1459 CmdArgs.push_back(Elt: 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.
1468static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
1469 StringRef Segment, StringRef Section) {
1470 for (const char *A : {"-sectalign", Args.MakeArgString(Str: Segment),
1471 Args.MakeArgString(Str: Section), "0x4000"})
1472 CmdArgs.push_back(Elt: A);
1473}
1474
1475void Darwin::addProfileRTLibs(const ArgList &Args,
1476 ArgStringList &CmdArgs) const {
1477 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1478 return;
1479
1480 AddLinkRuntimeLib(Args, CmdArgs, Component: "profile",
1481 Opts: 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, Symbol: "___gcov_dump");
1490 addExportedSymbol(CmdArgs, Symbol: "___gcov_reset");
1491 addExportedSymbol(CmdArgs, Symbol: "_writeout_fn_list");
1492 addExportedSymbol(CmdArgs, Symbol: "_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, Segment: "__DATA",
1508 Section: llvm::getInstrProfSectionName(IPSK, OF: llvm::Triple::MachO,
1509 /*AddSegmentInfo=*/false));
1510 }
1511 }
1512}
1513
1514void 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, Component: Sanitizer, Opts: RLO, IsShared: Shared);
1520}
1521
1522ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
1523 const ArgList &Args) const {
1524 if (Arg* A = Args.getLastArg(Ids: options::OPT_rtlib_EQ)) {
1525 StringRef Value = A->getValue();
1526 if (Value != "compiler-rt" && Value != "platform")
1527 getDriver().Diag(DiagID: clang::diag::err_drv_unsupported_rtlib_for_platform)
1528 << Value << "darwin";
1529 }
1530
1531 return ToolChain::RLT_CompilerRT;
1532}
1533
1534void 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(Ids: options::OPT_static) ||
1543 Args.hasArg(Ids: options::OPT_fapple_kext) ||
1544 Args.hasArg(Ids: options::OPT_mkernel)) {
1545 if (ForceLinkBuiltinRT)
1546 AddLinkRuntimeLib(Args, CmdArgs, Component: "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(Ids: options::OPT_static_libgcc)) {
1554 getDriver().Diag(DiagID: diag::err_drv_unsupported_opt) << A->getAsString(Args);
1555 return;
1556 }
1557
1558 const SanitizerArgs &Sanitize = getSanitizerArgs(JobArgs: 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(DiagID: 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, Sanitizer: "asan_abi", /*shared=*/Shared: false);
1582 } else {
1583 assert(Sanitize.needsSharedRt() &&
1584 "Static sanitizer runtimes not supported");
1585 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "asan");
1586 }
1587 }
1588 if (Sanitize.needsRtsanRt()) {
1589 assert(Sanitize.needsSharedRt() &&
1590 "Static sanitizer runtimes not supported");
1591 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "rtsan");
1592 }
1593 if (Sanitize.needsLsanRt())
1594 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "lsan");
1595 if (Sanitize.needsUbsanRt()) {
1596 assert(Sanitize.needsSharedRt() &&
1597 "Static sanitizer runtimes not supported");
1598 AddLinkSanitizerLibArgs(
1599 Args, CmdArgs,
1600 Sanitizer: Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");
1601 }
1602 if (Sanitize.needsTsanRt()) {
1603 assert(Sanitize.needsSharedRt() &&
1604 "Static sanitizer runtimes not supported");
1605 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "tsan");
1606 }
1607 if (Sanitize.needsTysanRt())
1608 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "tysan");
1609 if (Sanitize.needsFuzzer() && !Args.hasArg(Ids: options::OPT_dynamiclib)) {
1610 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "fuzzer", /*shared=*/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, Component: "stats_client", Opts: RLO_AlwaysLink);
1617 AddLinkSanitizerLibArgs(Args, CmdArgs, Sanitizer: "stats");
1618 }
1619 }
1620
1621 if (Sanitize.needsMemProfRt())
1622 if (hasExportSymbolDirective(Args))
1623 addExportedSymbol(
1624 CmdArgs,
1625 Symbol: llvm::memprof::getMemprofOptionsSymbolDarwinLinkageName().data());
1626
1627 const XRayArgs &XRay = getXRayArgs(Args);
1628 if (XRay.needsXRayRt()) {
1629 AddLinkRuntimeLib(Args, CmdArgs, Component: "xray");
1630 AddLinkRuntimeLib(Args, CmdArgs, Component: "xray-basic");
1631 AddLinkRuntimeLib(Args, CmdArgs, Component: "xray-fdr");
1632 }
1633
1634 if (isTargetDriverKit() && !Args.hasArg(Ids: options::OPT_nodriverkitlib)) {
1635 CmdArgs.push_back(Elt: "-framework");
1636 CmdArgs.push_back(Elt: "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(Elt: "-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(V0: 5, V1: 0) &&
1652 !isTargetIOSSimulator()) ||
1653 (isTargetMacOSBased() && isMacosxVersionLT(V0: 10, V1: 6))))
1654 CmdArgs.push_back(Elt: "-lgcc_s.1");
1655 AddLinkRuntimeLib(Args, CmdArgs, Component: "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.
1662static 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(Version&: SystemVersion);
1668
1669 unsigned Major, Minor, Micro;
1670 bool HadExtra;
1671 if (!Driver::GetReleaseVersion(Str: 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
1681namespace {
1682
1683/// The Darwin OS and version that was selected or inferred from arguments or
1684/// environment.
1685struct 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
1704 DarwinPlatformKind getPlatform() const { return Platform; }
1705
1706 DarwinEnvironmentKind getEnvironment() const { return Environment; }
1707
1708 void setEnvironment(DarwinEnvironmentKind Kind) {
1709 Environment = Kind;
1710 InferSimulatorFromArch = false;
1711 }
1712
1713 const VersionTuple getOSVersion() const {
1714 return UnderlyingOSVersion.value_or(u: VersionTuple());
1715 }
1716
1717 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 }
1724 bool isValidOSVersion() const {
1725 return llvm::Triple::isValidVersionForOS(OSKind: getOSFromPlatform(Platform),
1726 Version: getOSVersion());
1727 }
1728
1729 VersionTuple getCanonicalOSVersion() const {
1730 return llvm::Triple::getCanonicalVersionForOS(
1731 OSKind: getOSFromPlatform(Platform), Version: getOSVersion(), /*IsInValidRange=*/true);
1732 }
1733
1734 void setOSVersion(const VersionTuple &Version) {
1735 UnderlyingOSVersion = Version;
1736 }
1737
1738 bool hasOSVersion() const { return UnderlyingOSVersion.has_value(); }
1739
1740 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.
1747 bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
1748
1749 /// Returns true if the simulator environment can be inferred from the arch.
1750 bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
1751
1752 const std::optional<llvm::Triple> &getTargetVariantTriple() const {
1753 return TargetVariantTriple;
1754 }
1755
1756 /// Adds the -m<os>-version-min argument to the compiler invocation.
1757 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(BaseArg: nullptr, Opt: Opts.getOption(Opt), Value: OSVersionStr);
1785 Args.append(A: Arg);
1786 }
1787
1788 /// Returns the OS version with the argument / environment variable that
1789 /// specified it.
1790 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.
1808 std::string getInferredSource() {
1809 assert(!isExplicitlySpecified() && "OS version was not inferred");
1810 return InferredSource.str();
1811 }
1812
1813 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 Kind: DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
1827 if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
1828 Key: OSVersion, MinimumValue: ZipperedOSVersion, MaximumValue: 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
1851 createFromTarget(const llvm::Triple &TT, Arg *A,
1852 std::optional<llvm::Triple> TargetVariantTriple,
1853 const std::optional<DarwinSDKInfo> &SDKInfo) {
1854 DarwinPlatform Result(TargetArg, getPlatformFromOS(OS: TT.getOS()),
1855 TT.getOSVersion(), A);
1856 VersionTuple OsVersion = TT.getOSVersion();
1857 Result.TargetVariantTriple = TargetVariantTriple;
1858 Result.setEnvironment(EnvType: TT.getEnvironment(), OSVersion: OsVersion, SDKInfo);
1859 return Result;
1860 }
1861 static DarwinPlatform
1862 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(EnvType: Environment, OSVersion, SDKInfo);
1868 return Result;
1869 }
1870 static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
1871 bool IsSimulator) {
1872 DarwinPlatform Result{OSVersionArg, Platform,
1873 getVersionFromString(Input: A->getValue()), A};
1874 if (IsSimulator)
1875 Result.Environment = DarwinEnvironmentKind::Simulator;
1876 return Result;
1877 }
1878 static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
1879 StringRef EnvVarName,
1880 StringRef OSVersion) {
1881 DarwinPlatform Result(DeploymentTargetEnv, Platform,
1882 getVersionFromString(Input: OSVersion));
1883 Result.EnvVarName = EnvVarName;
1884 return Result;
1885 }
1886 static DarwinPlatform createFromSDK(StringRef SDKRoot,
1887 DarwinPlatformKind Platform,
1888 StringRef Value,
1889 bool IsSimulator = false) {
1890 DarwinPlatform Result(InferredFromSDK, Platform,
1891 getVersionFromString(Input: Value));
1892 if (IsSimulator)
1893 Result.Environment = DarwinEnvironmentKind::Simulator;
1894 Result.InferSimulatorFromArch = false;
1895 Result.InferredSource = SDKRoot;
1896 return Result;
1897 }
1898 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.
1909 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
1917private:
1918 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
1919 : Kind(Kind), Platform(Platform),
1920 Arguments({Argument, VersionTuple().getAsString()}) {}
1921 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
1929 static VersionTuple getVersionFromString(const StringRef Input) {
1930 llvm::VersionTuple Version;
1931 bool IsValid = !Version.tryParse(string: Input);
1932 assert(IsValid && "unable to convert input version to version tuple");
1933 (void)IsValid;
1934 return Version;
1935 }
1936
1937 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
1957 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.
2000std::optional<DarwinPlatform>
2001getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
2002 const Driver &TheDriver) {
2003 Arg *macOSVersion = Args.getLastArg(Ids: options::OPT_mmacos_version_min_EQ);
2004 Arg *iOSVersion = Args.getLastArg(Ids: options::OPT_mios_version_min_EQ,
2005 Ids: options::OPT_mios_simulator_version_min_EQ);
2006 Arg *TvOSVersion =
2007 Args.getLastArg(Ids: options::OPT_mtvos_version_min_EQ,
2008 Ids: options::OPT_mtvos_simulator_version_min_EQ);
2009 Arg *WatchOSVersion =
2010 Args.getLastArg(Ids: options::OPT_mwatchos_version_min_EQ,
2011 Ids: 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(DiagID: diag::err_drv_missing_version_number)
2018 << VersionArg->getAsString(Args);
2019 return std::nullopt;
2020 }
2021 return DarwinPlatform::createOSVersionArg(Platform, A: VersionArg,
2022 /*IsSimulator=*/IsSimulator);
2023 };
2024
2025 if (macOSVersion) {
2026 if (iOSVersion || TvOSVersion || WatchOSVersion) {
2027 TheDriver.Diag(DiagID: 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(DiagID: 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(DiagID: 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.
2064std::optional<DarwinPlatform>
2065getDeploymentTargetFromEnvironmentVariables(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(First: llvm::ArrayRef(EnvVars))) {
2079 if (char *Env = ::getenv(name: 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(DiagID: diag::err_drv_conflicting_deployment_targets)
2106 << Targets[FirstTarget] << Targets[I];
2107 }
2108 }
2109
2110 for (const auto &Target : llvm::enumerate(First: llvm::ArrayRef(Targets))) {
2111 if (!Target.value().empty())
2112 return DarwinPlatform::createDeploymentTargetEnv(
2113 Platform: (Darwin::DarwinPlatformKind)Target.index(), EnvVarName: EnvVars[Target.index()],
2114 OSVersion: 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.
2121static StringRef dropSDKNamePrefix(StringRef SDKName) {
2122 size_t PrefixPos = SDKName.find(C: '.');
2123 if (PrefixPos == StringRef::npos)
2124 return "";
2125 return SDKName.substr(Start: 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.
2131std::optional<DarwinPlatform>
2132inferDeploymentTargetFromSDK(DerivedArgList &Args,
2133 const std::optional<DarwinSDKInfo> &SDKInfo) {
2134 const Arg *A = Args.getLastArg(Ids: 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(Chars: "0123456789");
2150 size_t EndVer = SDK.find_last_of(Chars: "0123456789");
2151 if (StartVer != StringRef::npos && EndVer > StartVer)
2152 Version = std::string(SDK.slice(Start: StartVer, End: 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(Prefix: "iPhoneOS") || SDK.starts_with(Prefix: "iPhoneSimulator"))
2160 return DarwinPlatform::createFromSDK(
2161 SDKRoot: isysroot, Platform: Darwin::IPhoneOS, Value: Version,
2162 /*IsSimulator=*/SDK.starts_with(Prefix: "iPhoneSimulator"));
2163 else if (SDK.starts_with(Prefix: "MacOSX"))
2164 return DarwinPlatform::createFromSDK(SDKRoot: isysroot, Platform: Darwin::MacOS,
2165 Value: getSystemOrSDKMacOSVersion(MacOSSDKVersion: Version));
2166 else if (SDK.starts_with(Prefix: "WatchOS") || SDK.starts_with(Prefix: "WatchSimulator"))
2167 return DarwinPlatform::createFromSDK(
2168 SDKRoot: isysroot, Platform: Darwin::WatchOS, Value: Version,
2169 /*IsSimulator=*/SDK.starts_with(Prefix: "WatchSimulator"));
2170 else if (SDK.starts_with(Prefix: "AppleTVOS") ||
2171 SDK.starts_with(Prefix: "AppleTVSimulator"))
2172 return DarwinPlatform::createFromSDK(
2173 SDKRoot: isysroot, Platform: Darwin::TvOS, Value: Version,
2174 /*IsSimulator=*/SDK.starts_with(Prefix: "AppleTVSimulator"));
2175 else if (SDK.starts_with(Prefix: "XR"))
2176 return DarwinPlatform::createFromSDK(
2177 SDKRoot: isysroot, Platform: Darwin::XROS, Value: Version,
2178 /*IsSimulator=*/SDK.contains(Other: "Simulator"));
2179 else if (SDK.starts_with(Prefix: "DriverKit"))
2180 return DarwinPlatform::createFromSDK(SDKRoot: isysroot, Platform: Darwin::DriverKit,
2181 Value: 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(SDKName: SDK));
2188}
2189// Compute & get the OS Version when the target triple omitted one.
2190VersionTuple 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(Version&: OsVersion);
2203 else if (!Triple.getMacOSXVersion(Version&: OsVersion))
2204 TheDriver.Diag(DiagID: 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(NewMajor: 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.
2235std::optional<DarwinPlatform>
2236inferDeploymentTargetFromArch(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 Arch: MachOArchName, OS: OSTy, Version: getInferredOSVersion(OS: OSTy, Triple, TheDriver));
2256}
2257
2258/// Returns the deployment target that's specified using the -target option.
2259std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
2260 DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
2261 const std::optional<DarwinSDKInfo> &SDKInfo) {
2262 if (!Args.hasArg(Ids: 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(Ids: 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(DiagID: diag::err_drv_target_variant_invalid)
2289 << A->getSpelling() << A->getValue();
2290 }
2291 }
2292 DarwinPlatform PlatformAndVersion = DarwinPlatform::createFromTarget(
2293 TT: Triple, A: Args.getLastArg(Ids: options::OPT_target), TargetVariantTriple,
2294 SDKInfo);
2295
2296 return PlatformAndVersion;
2297}
2298
2299/// Returns the deployment target that's specified using the -mtargetos option.
2300std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
2301 DerivedArgList &Args, const Driver &TheDriver,
2302 const std::optional<DarwinSDKInfo> &SDKInfo) {
2303 auto *A = Args.getLastArg(Ids: 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(DiagID: 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(DiagID: diag::err_drv_invalid_version_number)
2323 << A->getAsString(Args);
2324 return std::nullopt;
2325 }
2326 return DarwinPlatform::createFromMTargetOS(OS: TT.getOS(), OSVersion: Version,
2327 Environment: TT.getEnvironment(), A, SDKInfo);
2328}
2329
2330std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
2331 const ArgList &Args,
2332 const Driver &TheDriver) {
2333 const Arg *A = Args.getLastArg(Ids: options::OPT_isysroot);
2334 if (!A)
2335 return std::nullopt;
2336 StringRef isysroot = A->getValue();
2337 auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, SDKRootPath: isysroot);
2338 if (!SDKInfoOrErr) {
2339 llvm::consumeError(Err: SDKInfoOrErr.takeError());
2340 TheDriver.Diag(DiagID: diag::warn_drv_darwin_sdk_invalid_settings);
2341 return std::nullopt;
2342 }
2343 return *SDKInfoOrErr;
2344}
2345
2346} // namespace
2347
2348void 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(Ids: options::OPT_isysroot)) {
2355 // Warn if the path does not exist.
2356 if (!getVFS().exists(Path: A->getValue()))
2357 getDriver().Diag(DiagID: clang::diag::warn_missing_sysroot) << A->getValue();
2358 } else {
2359 if (char *env = ::getenv(name: "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(path: env) && getVFS().exists(Path: env) &&
2363 StringRef(env) != "/") {
2364 Args.append(A: Args.MakeSeparateArg(
2365 BaseArg: nullptr, Opt: Opts.getOption(Opt: options::OPT_isysroot), Value: 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(VFS&: getVFS(), Args, TheDriver: getDriver());
2373
2374 // The OS and the version can be specified using the -target argument.
2375 std::optional<DarwinPlatform> PlatformAndVersion =
2376 getDeploymentTargetFromTargetArg(Args, Triple: getTriple(), TheDriver: getDriver(), SDKInfo);
2377 if (PlatformAndVersion) {
2378 // Disallow mixing -target and -mtargetos=.
2379 if (const auto *MTargetOSArg = Args.getLastArg(Ids: options::OPT_mtargetos_EQ)) {
2380 std::string TargetArgStr = PlatformAndVersion->getAsString(Args, Opts);
2381 std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
2382 getDriver().Diag(DiagID: 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(OS: getTriple().getOS(), Triple: getTriple(), TheDriver: getDriver()));
2390
2391 std::optional<DarwinPlatform> PlatformAndVersionFromOSVersionArg =
2392 getDeploymentTargetFromOSVersionArg(Args, TheDriver: 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 Str: PlatformAndVersion->getOSVersion().getAsString(), Major&: TargetMajor,
2402 Minor&: TargetMinor, Micro&: TargetMicro, HadExtra&: TargetExtra) &&
2403 Driver::GetReleaseVersion(
2404 Str: PlatformAndVersionFromOSVersionArg->getOSVersion().getAsString(),
2405 Major&: ArgMajor, Minor&: ArgMinor, Micro&: ArgMicro, HadExtra&: 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(DiagID: clang::diag::warn_drv_overriding_option)
2423 << OSVersionArg << TargetArg;
2424 }
2425 }
2426 }
2427 } else if ((PlatformAndVersion = getDeploymentTargetFromMTargetOSArg(
2428 Args, TheDriver: 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, TheDriver: getDriver());
2433 if (PlatformAndVersionFromOSVersionArg) {
2434 std::string MTargetOSArgStr = PlatformAndVersion->getAsString(Args, Opts);
2435 std::string OSVersionArgStr =
2436 PlatformAndVersionFromOSVersionArg->getAsString(Args, Opts);
2437 getDriver().Diag(DiagID: 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, TheDriver: getDriver());
2443 // If no deployment target was specified on the command line, check for
2444 // environment defines.
2445 if (!PlatformAndVersion) {
2446 PlatformAndVersion =
2447 getDeploymentTargetFromEnvironmentVariables(TheDriver: getDriver(), Triple: 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, Toolchain: *this, Triple: getTriple(), TheDriver: getDriver());
2471 }
2472
2473 assert(PlatformAndVersion && "Unable to infer Darwin variant");
2474 if (!PlatformAndVersion->isValidOSVersion()) {
2475 if (PlatformAndVersion->isExplicitlySpecified())
2476 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
2477 << PlatformAndVersion->getAsString(Args, Opts);
2478 else
2479 getDriver().Diag(DiagID: 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(DiagID: 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(Str: OSVersionStr, Major, Minor, Micro,
2506 HadExtra) ||
2507 HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
2508 Micro >= 100)
2509 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
2510 << PlatformAndVersion->getAsString(Args, Opts);
2511 } else if (Platform == IPhoneOS) {
2512 if (!Driver::GetReleaseVersion(Str: OSVersionStr, Major, Minor, Micro,
2513 HadExtra) ||
2514 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2515 getDriver().Diag(DiagID: 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(DiagID: 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(DiagID: diag::err_invalid_macos_32bit_deployment_target);
2533 else
2534 getDriver().Diag(DiagID: 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(Str: OSVersionStr, Major, Minor, Micro,
2545 HadExtra) ||
2546 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2547 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
2548 << PlatformAndVersion->getAsString(Args, Opts);
2549 } else if (Platform == WatchOS) {
2550 if (!Driver::GetReleaseVersion(Str: OSVersionStr, Major, Minor, Micro,
2551 HadExtra) ||
2552 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2553 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
2554 << PlatformAndVersion->getAsString(Args, Opts);
2555 } else if (Platform == DriverKit) {
2556 if (!Driver::GetReleaseVersion(Str: OSVersionStr, Major, Minor, Micro,
2557 HadExtra) ||
2558 HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
2559 Micro >= 100)
2560 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
2561 << PlatformAndVersion->getAsString(Args, Opts);
2562 } else if (Platform == XROS) {
2563 if (!Driver::GetReleaseVersion(Str: OSVersionStr, Major, Minor, Micro,
2564 HadExtra) ||
2565 HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
2566 Micro >= 100)
2567 getDriver().Diag(DiagID: 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, NativeTargetVersion: ZipperedOSVersion);
2583 TargetVariantTriple = PlatformAndVersion->getTargetVariantTriple();
2584 if (TargetVariantTriple &&
2585 !llvm::Triple::isValidVersionForOS(OSKind: TargetVariantTriple->getOS(),
2586 Version: TargetVariantTriple->getOSVersion())) {
2587 getDriver().Diag(DiagID: diag::err_drv_invalid_version_number)
2588 << TargetVariantTriple->str();
2589 }
2590
2591 if (const Arg *A = Args.getLastArg(Ids: options::OPT_isysroot)) {
2592 StringRef SDK = getSDKName(isysroot: A->getValue());
2593 if (SDK.size() > 0) {
2594 size_t StartVer = SDK.find_first_of(Chars: "0123456789");
2595 StringRef SDKName = SDK.slice(Start: 0, End: StartVer);
2596 if (!SDKName.starts_with(Prefix: getPlatformFamily()) &&
2597 !dropSDKNamePrefix(SDKName).starts_with(Prefix: getPlatformFamily()))
2598 getDriver().Diag(DiagID: 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).
2607static void AppendPlatformPrefix(SmallString<128> &Path,
2608 const llvm::Triple &T) {
2609 if (T.isDriverKit()) {
2610 llvm::sys::path::append(path&: Path, a: "System", b: "DriverKit");
2611 }
2612}
2613
2614// Returns the effective sysroot from either -isysroot or --sysroot, plus the
2615// platform prefix (if any).
2616llvm::SmallString<128>
2617AppleMachO::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2618 llvm::SmallString<128> Path("/");
2619 if (DriverArgs.hasArg(Ids: options::OPT_isysroot))
2620 Path = DriverArgs.getLastArgValue(Id: options::OPT_isysroot);
2621 else if (!getDriver().SysRoot.empty())
2622 Path = getDriver().SysRoot;
2623
2624 if (hasEffectiveTriple()) {
2625 AppendPlatformPrefix(Path, T: getEffectiveTriple());
2626 }
2627 return Path;
2628}
2629
2630void 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(Ids: options::OPT_nostdinc);
2638 bool NoStdlibInc = DriverArgs.hasArg(Ids: options::OPT_nostdlibinc);
2639 bool NoBuiltinInc = DriverArgs.hasFlag(
2640 Pos: options::OPT_nobuiltininc, Neg: options::OPT_ibuiltininc, /*Default=*/false);
2641 bool ForceBuiltinInc = DriverArgs.hasFlag(
2642 Pos: options::OPT_ibuiltininc, Neg: 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(path&: P, a: "usr", b: "local", c: "include");
2648 addSystemInclude(DriverArgs, CC1Args, Path: 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(path&: P, a: "include");
2655 addSystemInclude(DriverArgs, CC1Args, Path: 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(A&: dirs, Separator: ":");
2666 for (llvm::StringRef dir : dirs) {
2667 llvm::StringRef Prefix =
2668 llvm::sys::path::is_absolute(path: dir) ? "" : llvm::StringRef(Sysroot);
2669 addExternCSystemInclude(DriverArgs, CC1Args, Path: Prefix + dir);
2670 }
2671 } else {
2672 // Otherwise, add <sysroot>/usr/include.
2673 SmallString<128> P(Sysroot);
2674 llvm::sys::path::append(path&: P, a: "usr", b: "include");
2675 addExternCSystemInclude(DriverArgs, CC1Args, Path: P.str());
2676 }
2677}
2678
2679void DarwinClang::AddClangSystemIncludeArgs(
2680 const llvm::opt::ArgList &DriverArgs,
2681 llvm::opt::ArgStringList &CC1Args) const {
2682 AppleMachO::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
2683
2684 if (DriverArgs.hasArg(Ids: options::OPT_nostdinc, Ids: 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(path&: P1, a: "System", b: "Library", c: "Frameworks");
2694 llvm::sys::path::append(path&: P2, a: "System", b: "Library", c: "SubFrameworks");
2695 llvm::sys::path::append(path&: P3, a: "Library", b: "Frameworks");
2696 addSystemFrameworkIncludes(DriverArgs, CC1Args, Paths: {P1, P2, P3});
2697}
2698
2699bool 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(path&: Base, a: Version);
2706
2707 // Add the base dir
2708 addSystemInclude(DriverArgs, CC1Args, Path: Base);
2709
2710 // Add the multilib dirs
2711 {
2712 llvm::SmallString<128> P = Base;
2713 if (!ArchDir.empty())
2714 llvm::sys::path::append(path&: P, a: ArchDir);
2715 if (!BitDir.empty())
2716 llvm::sys::path::append(path&: P, a: BitDir);
2717 addSystemInclude(DriverArgs, CC1Args, Path: P);
2718 }
2719
2720 // Add the backward dir
2721 {
2722 llvm::SmallString<128> P = Base;
2723 llvm::sys::path::append(path&: P, a: "backward");
2724 addSystemInclude(DriverArgs, CC1Args, Path: P);
2725 }
2726
2727 return getVFS().exists(Path: Base);
2728}
2729
2730void 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(Ids: options::OPT_nostdinc, Ids: options::OPT_nostdlibinc,
2741 Ids: options::OPT_nostdincxx))
2742 return;
2743
2744 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2745
2746 switch (GetCXXStdlibType(Args: 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(path&: InstallBin, a: "..", b: "include", c: "c++", d: "v1");
2763 if (getVFS().exists(Path: InstallBin)) {
2764 addSystemInclude(DriverArgs, CC1Args, Path: InstallBin);
2765 return;
2766 } else if (DriverArgs.hasArg(Ids: 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(path&: SysrootUsr, a: "usr", b: "include", c: "c++", d: "v1");
2774 if (getVFS().exists(Path: SysrootUsr)) {
2775 addSystemInclude(DriverArgs, CC1Args, Path: SysrootUsr);
2776 return;
2777 } else if (DriverArgs.hasArg(Ids: 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
2792void AppleMachO::AddGnuCPlusPlusIncludePaths(
2793 const llvm::opt::ArgList &DriverArgs,
2794 llvm::opt::ArgStringList &CC1Args) const {}
2795
2796void 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(path&: UsrIncludeCxx, a: "usr", b: "include", c: "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, Base: UsrIncludeCxx, Version: "4.2.1", ArchDir: "i686-apple-darwin10",
2812 BitDir: arch == llvm::Triple::x86_64 ? "x86_64" : "");
2813 IsBaseFound |= AddGnuCPlusPlusIncludePaths(
2814 DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.0.0", ArchDir: "i686-apple-darwin8", BitDir: "");
2815 break;
2816
2817 case llvm::Triple::arm:
2818 case llvm::Triple::thumb:
2819 IsBaseFound =
2820 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1",
2821 ArchDir: "arm-apple-darwin10", BitDir: "v7");
2822 IsBaseFound |=
2823 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1",
2824 ArchDir: "arm-apple-darwin10", BitDir: "v6");
2825 break;
2826
2827 case llvm::Triple::aarch64:
2828 IsBaseFound =
2829 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1",
2830 ArchDir: "arm64-apple-darwin10", BitDir: "");
2831 break;
2832 }
2833
2834 if (!IsBaseFound) {
2835 getDriver().Diag(DiagID: diag::warn_drv_libstdcxx_not_found);
2836 }
2837}
2838
2839void 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(Elt: "-lc++");
2846 if (Args.hasArg(Ids: options::OPT_fexperimental_library))
2847 CmdArgs.push_back(Elt: "-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(Ids: options::OPT_isysroot)) {
2858 SmallString<128> P(A->getValue());
2859 llvm::sys::path::append(path&: P, a: "usr", b: "lib", c: "libstdc++.dylib");
2860
2861 if (!getVFS().exists(Path: P)) {
2862 llvm::sys::path::remove_filename(path&: P);
2863 llvm::sys::path::append(path&: P, a: "libstdc++.6.dylib");
2864 if (getVFS().exists(Path: P)) {
2865 CmdArgs.push_back(Elt: Args.MakeArgString(Str: 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(Path: "/usr/lib/libstdc++.dylib") &&
2875 getVFS().exists(Path: "/usr/lib/libstdc++.6.dylib")) {
2876 CmdArgs.push_back(Elt: "/usr/lib/libstdc++.6.dylib");
2877 return;
2878 }
2879
2880 // Otherwise, let the linker search.
2881 CmdArgs.push_back(Elt: "-lstdc++");
2882 break;
2883 }
2884}
2885
2886void 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(path&: P, a: "lib", b: "darwin");
2894
2895 // Use the newer cc_kext for iOS ARM after 6.0.
2896 if (isTargetWatchOS()) {
2897 llvm::sys::path::append(path&: P, a: "libclang_rt.cc_kext_watchos.a");
2898 } else if (isTargetTvOS()) {
2899 llvm::sys::path::append(path&: P, a: "libclang_rt.cc_kext_tvos.a");
2900 } else if (isTargetIPhoneOS()) {
2901 llvm::sys::path::append(path&: P, a: "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 path&: P, a: llvm::Twine("libclang_rt.cc_kext_") +
2907 llvm::Triple::getOSTypeName(Kind: llvm::Triple::XROS) + ".a");
2908 } else {
2909 llvm::sys::path::append(path&: P, a: "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(Path: P))
2915 CmdArgs.push_back(Elt: Args.MakeArgString(Str: P));
2916}
2917
2918DerivedArgList *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(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_static));
2944 break;
2945
2946 case options::OPT_dependency_file:
2947 DAL->AddSeparateArg(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_MF), Value: A->getValue());
2948 break;
2949
2950 case options::OPT_gfull:
2951 DAL->AddFlagArg(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_g_Flag));
2952 DAL->AddFlagArg(
2953 BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_fno_eliminate_unused_debug_symbols));
2954 break;
2955
2956 case options::OPT_gused:
2957 DAL->AddFlagArg(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_g_Flag));
2958 DAL->AddFlagArg(
2959 BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_feliminate_unused_debug_symbols));
2960 break;
2961
2962 case options::OPT_shared:
2963 DAL->AddFlagArg(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_dynamiclib));
2964 break;
2965
2966 case options::OPT_fconstant_cfstrings:
2967 DAL->AddFlagArg(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_mconstant_cfstrings));
2968 break;
2969
2970 case options::OPT_fno_constant_cfstrings:
2971 DAL->AddFlagArg(BaseArg: A, Opt: Opts.getOption(Opt: options::OPT_mno_constant_cfstrings));
2972 break;
2973
2974 case options::OPT_Wnonportable_cfstrings:
2975 DAL->AddFlagArg(BaseArg: A,
2976 Opt: Opts.getOption(Opt: options::OPT_mwarn_nonportable_cfstrings));
2977 break;
2978
2979 case options::OPT_Wno_nonportable_cfstrings:
2980 DAL->AddFlagArg(
2981 BaseArg: A, Opt: Opts.getOption(Opt: 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(Opt: options::OPT_mcpu_EQ);
2991 const Option MArch = Opts.getOption(Opt: 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(BaseArg: nullptr, Opt: MCpu, Value: "601");
2999 else if (Name == "ppc603")
3000 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "603");
3001 else if (Name == "ppc604")
3002 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "604");
3003 else if (Name == "ppc604e")
3004 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "604e");
3005 else if (Name == "ppc750")
3006 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "750");
3007 else if (Name == "ppc7400")
3008 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "7400");
3009 else if (Name == "ppc7450")
3010 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "7450");
3011 else if (Name == "ppc970")
3012 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "970");
3013
3014 else if (Name == "ppc64" || Name == "ppc64le")
3015 DAL->AddFlagArg(BaseArg: nullptr, Opt: Opts.getOption(Opt: options::OPT_m64));
3016
3017 else if (Name == "i386")
3018 ;
3019 else if (Name == "i486")
3020 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "i486");
3021 else if (Name == "i586")
3022 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "i586");
3023 else if (Name == "i686")
3024 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "i686");
3025 else if (Name == "pentium")
3026 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentium");
3027 else if (Name == "pentium2")
3028 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentium2");
3029 else if (Name == "pentpro")
3030 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentiumpro");
3031 else if (Name == "pentIIm3")
3032 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentium2");
3033
3034 else if (Name == "x86_64" || Name == "x86_64h")
3035 DAL->AddFlagArg(BaseArg: nullptr, Opt: Opts.getOption(Opt: options::OPT_m64));
3036
3037 else if (Name == "arm")
3038 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv4t");
3039 else if (Name == "armv4t")
3040 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv4t");
3041 else if (Name == "armv5")
3042 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv5tej");
3043 else if (Name == "xscale")
3044 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "xscale");
3045 else if (Name == "armv6")
3046 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv6k");
3047 else if (Name == "armv6m")
3048 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv6m");
3049 else if (Name == "armv7")
3050 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7a");
3051 else if (Name == "armv7em")
3052 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7em");
3053 else if (Name == "armv7k")
3054 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7k");
3055 else if (Name == "armv7m")
3056 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7m");
3057 else if (Name == "armv7s")
3058 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7s");
3059 }
3060
3061 return DAL;
3062}
3063
3064void 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(TC: *this, Args) == tools::arm::FloatABI::Hard)
3073 ? "hard"
3074 : "soft";
3075 CompilerRT += Args.hasArg(Ids: options::OPT_fPIC) ? "_pic" : "_static";
3076
3077 AddLinkRuntimeLib(Args, CmdArgs, Component: CompilerRT, Opts: RLO_IsEmbedded);
3078}
3079
3080bool Darwin::isAlignedAllocationUnavailable() const {
3081 llvm::Triple::OSType OS;
3082
3083 if (isTargetMacCatalyst())
3084 return TargetVersion < alignedAllocMinVersion(OS: 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
3107static bool
3108sdkSupportsBuiltinModules(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
3139static inline llvm::VersionTuple
3140sizedDeallocMinVersion(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
3157bool Darwin::isSizedDeallocationUnavailable() const {
3158 llvm::Triple::OSType OS;
3159
3160 if (isTargetMacCatalyst())
3161 return TargetVersion < sizedDeallocMinVersion(OS: 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
3184void 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, enable pointer authentication (for the return address and
3191 // indirect calls), as well as usage of the intrinsics.
3192 if (getArchName() == "arm64e") {
3193 if (!DriverArgs.hasArg(Ids: options::OPT_fptrauth_returns,
3194 Ids: options::OPT_fno_ptrauth_returns))
3195 CC1Args.push_back(Elt: "-fptrauth-returns");
3196
3197 if (!DriverArgs.hasArg(Ids: options::OPT_fptrauth_intrinsics,
3198 Ids: options::OPT_fno_ptrauth_intrinsics))
3199 CC1Args.push_back(Elt: "-fptrauth-intrinsics");
3200
3201 if (!DriverArgs.hasArg(Ids: options::OPT_fptrauth_calls,
3202 Ids: options::OPT_fno_ptrauth_calls))
3203 CC1Args.push_back(Elt: "-fptrauth-calls");
3204
3205 if (!DriverArgs.hasArg(Ids: options::OPT_fptrauth_indirect_gotos,
3206 Ids: options::OPT_fno_ptrauth_indirect_gotos))
3207 CC1Args.push_back(Elt: "-fptrauth-indirect-gotos");
3208
3209 if (!DriverArgs.hasArg(Ids: options::OPT_fptrauth_auth_traps,
3210 Ids: options::OPT_fno_ptrauth_auth_traps))
3211 CC1Args.push_back(Elt: "-fptrauth-auth-traps");
3212 }
3213}
3214
3215void Darwin::addClangTargetOptions(
3216 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
3217 Action::OffloadKind DeviceOffloadKind) const {
3218
3219 MachO::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
3220
3221 // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
3222 // enabled or disabled aligned allocations.
3223 if (!DriverArgs.hasArgNoClaim(Ids: options::OPT_faligned_allocation,
3224 Ids: options::OPT_fno_aligned_allocation) &&
3225 isAlignedAllocationUnavailable())
3226 CC1Args.push_back(Elt: "-faligned-alloc-unavailable");
3227
3228 // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled
3229 // or disabled sized deallocations.
3230 if (!DriverArgs.hasArgNoClaim(Ids: options::OPT_fsized_deallocation,
3231 Ids: options::OPT_fno_sized_deallocation) &&
3232 isSizedDeallocationUnavailable())
3233 CC1Args.push_back(Elt: "-fno-sized-deallocation");
3234
3235 addClangCC1ASTargetOptions(Args: DriverArgs, CC1ASArgs&: CC1Args);
3236
3237 // Enable compatibility mode for NSItemProviderCompletionHandler in
3238 // Foundation/NSItemProvider.h.
3239 CC1Args.push_back(Elt: "-fcompatibility-qualified-id-block-type-checking");
3240
3241 // Give static local variables in inline functions hidden visibility when
3242 // -fvisibility-inlines-hidden is enabled.
3243 if (!DriverArgs.getLastArgNoClaim(
3244 Ids: options::OPT_fvisibility_inlines_hidden_static_local_var,
3245 Ids: options::OPT_fno_visibility_inlines_hidden_static_local_var))
3246 CC1Args.push_back(Elt: "-fvisibility-inlines-hidden-static-local-var");
3247
3248 // Earlier versions of the darwin SDK have the C standard library headers
3249 // all together in the Darwin module. That leads to module cycles with
3250 // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
3251 // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
3252 // darwin headers are in the Darwin module, there's a module cycle Darwin ->
3253 // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
3254 // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
3255 // but until then, the builtin headers need to join the system modules.
3256 // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
3257 // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
3258 // to fix the same problem with C++ headers, and is generally fragile.
3259 if (!sdkSupportsBuiltinModules(SDKInfo))
3260 CC1Args.push_back(Elt: "-fbuiltin-headers-in-system-modules");
3261
3262 if (!DriverArgs.hasArgNoClaim(Ids: options::OPT_fdefine_target_os_macros,
3263 Ids: options::OPT_fno_define_target_os_macros))
3264 CC1Args.push_back(Elt: "-fdefine-target-os-macros");
3265
3266 // Disable subdirectory modulemap search on sufficiently recent SDKs.
3267 if (SDKInfo &&
3268 !DriverArgs.hasFlag(Pos: options::OPT_fmodulemap_allow_subdirectory_search,
3269 Neg: options::OPT_fno_modulemap_allow_subdirectory_search,
3270 Default: false)) {
3271 bool RequiresSubdirectorySearch;
3272 VersionTuple SDKVersion = SDKInfo->getVersion();
3273 switch (TargetPlatform) {
3274 default:
3275 RequiresSubdirectorySearch = true;
3276 break;
3277 case MacOS:
3278 RequiresSubdirectorySearch = SDKVersion < VersionTuple(15, 0);
3279 break;
3280 case IPhoneOS:
3281 case TvOS:
3282 RequiresSubdirectorySearch = SDKVersion < VersionTuple(18, 0);
3283 break;
3284 case WatchOS:
3285 RequiresSubdirectorySearch = SDKVersion < VersionTuple(11, 0);
3286 break;
3287 case XROS:
3288 RequiresSubdirectorySearch = SDKVersion < VersionTuple(2, 0);
3289 break;
3290 }
3291 if (!RequiresSubdirectorySearch)
3292 CC1Args.push_back(Elt: "-fno-modulemap-allow-subdirectory-search");
3293 }
3294}
3295
3296void Darwin::addClangCC1ASTargetOptions(
3297 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
3298 if (TargetVariantTriple) {
3299 CC1ASArgs.push_back(Elt: "-darwin-target-variant-triple");
3300 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: TargetVariantTriple->getTriple()));
3301 }
3302
3303 if (SDKInfo) {
3304 /// Pass the SDK version to the compiler when the SDK information is
3305 /// available.
3306 auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
3307 std::string Arg;
3308 llvm::raw_string_ostream OS(Arg);
3309 OS << "-target-sdk-version=" << V;
3310 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: Arg));
3311 };
3312
3313 if (isTargetMacCatalyst()) {
3314 if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
3315 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3316 std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
3317 Key: SDKInfo->getVersion(), MinimumValue: minimumMacCatalystDeploymentTarget(),
3318 MaximumValue: std::nullopt);
3319 EmitTargetSDKVersionArg(
3320 SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
3321 }
3322 } else {
3323 EmitTargetSDKVersionArg(SDKInfo->getVersion());
3324 }
3325
3326 /// Pass the target variant SDK version to the compiler when the SDK
3327 /// information is available and is required for target variant.
3328 if (TargetVariantTriple) {
3329 if (isTargetMacCatalyst()) {
3330 std::string Arg;
3331 llvm::raw_string_ostream OS(Arg);
3332 OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
3333 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: Arg));
3334 } else if (const auto *MacOStoMacCatalystMapping =
3335 SDKInfo->getVersionMapping(
3336 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3337 if (std::optional<VersionTuple> SDKVersion =
3338 MacOStoMacCatalystMapping->map(
3339 Key: SDKInfo->getVersion(), MinimumValue: minimumMacCatalystDeploymentTarget(),
3340 MaximumValue: std::nullopt)) {
3341 std::string Arg;
3342 llvm::raw_string_ostream OS(Arg);
3343 OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
3344 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: Arg));
3345 }
3346 }
3347 }
3348 }
3349}
3350
3351DerivedArgList *
3352Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
3353 Action::OffloadKind DeviceOffloadKind) const {
3354 // First get the generic Apple args, before moving onto Darwin-specific ones.
3355 DerivedArgList *DAL =
3356 MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
3357
3358 // If no architecture is bound, none of the translations here are relevant.
3359 if (BoundArch.empty())
3360 return DAL;
3361
3362 // Add an explicit version min argument for the deployment target. We do this
3363 // after argument translation because -Xarch_ arguments may add a version min
3364 // argument.
3365 AddDeploymentTarget(Args&: *DAL);
3366
3367 // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
3368 // FIXME: It would be far better to avoid inserting those -static arguments,
3369 // but we can't check the deployment target in the translation code until
3370 // it is set here.
3371 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||
3372 (isTargetIOSBased() && !isIPhoneOSVersionLT(V0: 6, V1: 0))) {
3373 for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
3374 Arg *A = *it;
3375 ++it;
3376 if (A->getOption().getID() != options::OPT_mkernel &&
3377 A->getOption().getID() != options::OPT_fapple_kext)
3378 continue;
3379 assert(it != ie && "unexpected argument translation");
3380 A = *it;
3381 assert(A->getOption().getID() == options::OPT_static &&
3382 "missing expected -static argument");
3383 *it = nullptr;
3384 ++it;
3385 }
3386 }
3387
3388 auto Arch = tools::darwin::getArchTypeForMachOArchName(Str: BoundArch);
3389 if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
3390 if (Args.hasFlag(Pos: options::OPT_fomit_frame_pointer,
3391 Neg: options::OPT_fno_omit_frame_pointer, Default: false))
3392 getDriver().Diag(DiagID: clang::diag::warn_drv_unsupported_opt_for_target)
3393 << "-fomit-frame-pointer" << BoundArch;
3394 }
3395
3396 return DAL;
3397}
3398
3399ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
3400 // Unwind tables are not emitted if -fno-exceptions is supplied (except when
3401 // targeting x86_64).
3402 if (getArch() == llvm::Triple::x86_64 ||
3403 (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
3404 Args.hasFlag(Pos: options::OPT_fexceptions, Neg: options::OPT_fno_exceptions,
3405 Default: true)))
3406 return (getArch() == llvm::Triple::aarch64 ||
3407 getArch() == llvm::Triple::aarch64_32)
3408 ? UnwindTableLevel::Synchronous
3409 : UnwindTableLevel::Asynchronous;
3410
3411 return UnwindTableLevel::None;
3412}
3413
3414bool MachO::UseDwarfDebugFlags() const {
3415 if (const char *S = ::getenv(name: "RC_DEBUG_OPTIONS"))
3416 return S[0] != '\0';
3417 return false;
3418}
3419
3420std::string MachO::GetGlobalDebugPathRemapping() const {
3421 if (const char *S = ::getenv(name: "RC_DEBUG_PREFIX_MAP"))
3422 return S;
3423 return {};
3424}
3425
3426llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
3427 // Darwin uses SjLj exceptions on ARM.
3428 if (getTriple().getArch() != llvm::Triple::arm &&
3429 getTriple().getArch() != llvm::Triple::thumb)
3430 return llvm::ExceptionHandling::None;
3431
3432 // Only watchOS uses the new DWARF/Compact unwinding method.
3433 llvm::Triple Triple(ComputeLLVMTriple(Args));
3434 if (Triple.isWatchABI())
3435 return llvm::ExceptionHandling::DwarfCFI;
3436
3437 return llvm::ExceptionHandling::SjLj;
3438}
3439
3440bool Darwin::SupportsEmbeddedBitcode() const {
3441 assert(TargetInitialized && "Target not initialized!");
3442 if (isTargetIPhoneOS() && isIPhoneOSVersionLT(V0: 6, V1: 0))
3443 return false;
3444 return true;
3445}
3446
3447bool MachO::isPICDefault() const { return true; }
3448
3449bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
3450
3451bool MachO::isPICDefaultForced() const {
3452 return (getArch() == llvm::Triple::x86_64 ||
3453 getArch() == llvm::Triple::aarch64);
3454}
3455
3456bool MachO::SupportsProfiling() const {
3457 // Profiling instrumentation is only supported on x86.
3458 return getTriple().isX86();
3459}
3460
3461void Darwin::addMinVersionArgs(const ArgList &Args,
3462 ArgStringList &CmdArgs) const {
3463 VersionTuple TargetVersion = getTripleTargetVersion();
3464
3465 assert(!isTargetXROS() && "xrOS always uses -platform-version");
3466
3467 if (isTargetWatchOS())
3468 CmdArgs.push_back(Elt: "-watchos_version_min");
3469 else if (isTargetWatchOSSimulator())
3470 CmdArgs.push_back(Elt: "-watchos_simulator_version_min");
3471 else if (isTargetTvOS())
3472 CmdArgs.push_back(Elt: "-tvos_version_min");
3473 else if (isTargetTvOSSimulator())
3474 CmdArgs.push_back(Elt: "-tvos_simulator_version_min");
3475 else if (isTargetDriverKit())
3476 CmdArgs.push_back(Elt: "-driverkit_version_min");
3477 else if (isTargetIOSSimulator())
3478 CmdArgs.push_back(Elt: "-ios_simulator_version_min");
3479 else if (isTargetIOSBased())
3480 CmdArgs.push_back(Elt: "-iphoneos_version_min");
3481 else if (isTargetMacCatalyst())
3482 CmdArgs.push_back(Elt: "-maccatalyst_version_min");
3483 else {
3484 assert(isTargetMacOS() && "unexpected target");
3485 CmdArgs.push_back(Elt: "-macosx_version_min");
3486 }
3487
3488 VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
3489 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3490 TargetVersion = MinTgtVers;
3491 CmdArgs.push_back(Elt: Args.MakeArgString(Str: TargetVersion.getAsString()));
3492 if (TargetVariantTriple) {
3493 assert(isTargetMacOSBased() && "unexpected target");
3494 VersionTuple VariantTargetVersion;
3495 if (TargetVariantTriple->isMacOSX()) {
3496 CmdArgs.push_back(Elt: "-macosx_version_min");
3497 TargetVariantTriple->getMacOSXVersion(Version&: VariantTargetVersion);
3498 } else {
3499 assert(TargetVariantTriple->isiOS() &&
3500 TargetVariantTriple->isMacCatalystEnvironment() &&
3501 "unexpected target variant triple");
3502 CmdArgs.push_back(Elt: "-maccatalyst_version_min");
3503 VariantTargetVersion = TargetVariantTriple->getiOSVersion();
3504 }
3505 VersionTuple MinTgtVers =
3506 TargetVariantTriple->getMinimumSupportedOSVersion();
3507 if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
3508 VariantTargetVersion = MinTgtVers;
3509 CmdArgs.push_back(Elt: Args.MakeArgString(Str: VariantTargetVersion.getAsString()));
3510 }
3511}
3512
3513static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
3514 Darwin::DarwinEnvironmentKind Environment) {
3515 switch (Platform) {
3516 case Darwin::MacOS:
3517 return "macos";
3518 case Darwin::IPhoneOS:
3519 if (Environment == Darwin::MacCatalyst)
3520 return "mac catalyst";
3521 return "ios";
3522 case Darwin::TvOS:
3523 return "tvos";
3524 case Darwin::WatchOS:
3525 return "watchos";
3526 case Darwin::XROS:
3527 return "xros";
3528 case Darwin::DriverKit:
3529 return "driverkit";
3530 }
3531 llvm_unreachable("invalid platform");
3532}
3533
3534void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
3535 llvm::opt::ArgStringList &CmdArgs) const {
3536 auto EmitPlatformVersionArg =
3537 [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
3538 Darwin::DarwinEnvironmentKind TargetEnvironment,
3539 const llvm::Triple &TT) {
3540 // -platform_version <platform> <target_version> <sdk_version>
3541 // Both the target and SDK version support only up to 3 components.
3542 CmdArgs.push_back(Elt: "-platform_version");
3543 std::string PlatformName =
3544 getPlatformName(Platform: TargetPlatform, Environment: TargetEnvironment);
3545 if (TargetEnvironment == Darwin::Simulator)
3546 PlatformName += "-simulator";
3547 CmdArgs.push_back(Elt: Args.MakeArgString(Str: PlatformName));
3548 VersionTuple TargetVersion = TV.withoutBuild();
3549 if ((TargetPlatform == Darwin::IPhoneOS ||
3550 TargetPlatform == Darwin::TvOS) &&
3551 getTriple().getArchName() == "arm64e" &&
3552 TargetVersion.getMajor() < 14) {
3553 // arm64e slice is supported on iOS/tvOS 14+ only.
3554 TargetVersion = VersionTuple(14, 0);
3555 }
3556 VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
3557 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3558 TargetVersion = MinTgtVers;
3559 CmdArgs.push_back(Elt: Args.MakeArgString(Str: TargetVersion.getAsString()));
3560
3561 if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
3562 // Mac Catalyst programs must use the appropriate iOS SDK version
3563 // that corresponds to the macOS SDK version used for the compilation.
3564 std::optional<VersionTuple> iOSSDKVersion;
3565 if (SDKInfo) {
3566 if (const auto *MacOStoMacCatalystMapping =
3567 SDKInfo->getVersionMapping(
3568 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3569 iOSSDKVersion = MacOStoMacCatalystMapping->map(
3570 Key: SDKInfo->getVersion().withoutBuild(),
3571 MinimumValue: minimumMacCatalystDeploymentTarget(), MaximumValue: std::nullopt);
3572 }
3573 }
3574 CmdArgs.push_back(Elt: Args.MakeArgString(
3575 Str: (iOSSDKVersion ? *iOSSDKVersion
3576 : minimumMacCatalystDeploymentTarget())
3577 .getAsString()));
3578 return;
3579 }
3580
3581 if (SDKInfo) {
3582 VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
3583 if (!SDKVersion.getMinor())
3584 SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
3585 CmdArgs.push_back(Elt: Args.MakeArgString(Str: SDKVersion.getAsString()));
3586 } else {
3587 // Use an SDK version that's matching the deployment target if the SDK
3588 // version is missing. This is preferred over an empty SDK version
3589 // (0.0.0) as the system's runtime might expect the linked binary to
3590 // contain a valid SDK version in order for the binary to work
3591 // correctly. It's reasonable to use the deployment target version as
3592 // a proxy for the SDK version because older SDKs don't guarantee
3593 // support for deployment targets newer than the SDK versions, so that
3594 // rules out using some predetermined older SDK version, which leaves
3595 // the deployment target version as the only reasonable choice.
3596 CmdArgs.push_back(Elt: Args.MakeArgString(Str: TargetVersion.getAsString()));
3597 }
3598 };
3599 EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
3600 TargetEnvironment, getEffectiveTriple());
3601 if (!TargetVariantTriple)
3602 return;
3603 Darwin::DarwinPlatformKind Platform;
3604 Darwin::DarwinEnvironmentKind Environment;
3605 VersionTuple TargetVariantVersion;
3606 if (TargetVariantTriple->isMacOSX()) {
3607 TargetVariantTriple->getMacOSXVersion(Version&: TargetVariantVersion);
3608 Platform = Darwin::MacOS;
3609 Environment = Darwin::NativeEnvironment;
3610 } else {
3611 assert(TargetVariantTriple->isiOS() &&
3612 TargetVariantTriple->isMacCatalystEnvironment() &&
3613 "unexpected target variant triple");
3614 TargetVariantVersion = TargetVariantTriple->getiOSVersion();
3615 Platform = Darwin::IPhoneOS;
3616 Environment = Darwin::MacCatalyst;
3617 }
3618 EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
3619 *TargetVariantTriple);
3620}
3621
3622// Add additional link args for the -dynamiclib option.
3623static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
3624 ArgStringList &CmdArgs) {
3625 // Derived from darwin_dylib1 spec.
3626 if (D.isTargetIPhoneOS()) {
3627 if (D.isIPhoneOSVersionLT(V0: 3, V1: 1))
3628 CmdArgs.push_back(Elt: "-ldylib1.o");
3629 return;
3630 }
3631
3632 if (!D.isTargetMacOS())
3633 return;
3634 if (D.isMacosxVersionLT(V0: 10, V1: 5))
3635 CmdArgs.push_back(Elt: "-ldylib1.o");
3636 else if (D.isMacosxVersionLT(V0: 10, V1: 6))
3637 CmdArgs.push_back(Elt: "-ldylib1.10.5.o");
3638}
3639
3640// Add additional link args for the -bundle option.
3641static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
3642 ArgStringList &CmdArgs) {
3643 if (Args.hasArg(Ids: options::OPT_static))
3644 return;
3645 // Derived from darwin_bundle1 spec.
3646 if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(V0: 3, V1: 1)) ||
3647 (D.isTargetMacOS() && D.isMacosxVersionLT(V0: 10, V1: 6)))
3648 CmdArgs.push_back(Elt: "-lbundle1.o");
3649}
3650
3651// Add additional link args for the -pg option.
3652static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
3653 ArgStringList &CmdArgs) {
3654 if (D.isTargetMacOS() && D.isMacosxVersionLT(V0: 10, V1: 9)) {
3655 if (Args.hasArg(Ids: options::OPT_static) || Args.hasArg(Ids: options::OPT_object) ||
3656 Args.hasArg(Ids: options::OPT_preload)) {
3657 CmdArgs.push_back(Elt: "-lgcrt0.o");
3658 } else {
3659 CmdArgs.push_back(Elt: "-lgcrt1.o");
3660
3661 // darwin_crt2 spec is empty.
3662 }
3663 // By default on OS X 10.8 and later, we don't link with a crt1.o
3664 // file and the linker knows to use _main as the entry point. But,
3665 // when compiling with -pg, we need to link with the gcrt1.o file,
3666 // so pass the -no_new_main option to tell the linker to use the
3667 // "start" symbol as the entry point.
3668 if (!D.isMacosxVersionLT(V0: 10, V1: 8))
3669 CmdArgs.push_back(Elt: "-no_new_main");
3670 } else {
3671 D.getDriver().Diag(DiagID: diag::err_drv_clang_unsupported_opt_pg_darwin)
3672 << D.isTargetMacOSBased();
3673 }
3674}
3675
3676static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
3677 ArgStringList &CmdArgs) {
3678 // Derived from darwin_crt1 spec.
3679 if (D.isTargetIPhoneOS()) {
3680 if (D.getArch() == llvm::Triple::aarch64)
3681 ; // iOS does not need any crt1 files for arm64
3682 else if (D.isIPhoneOSVersionLT(V0: 3, V1: 1))
3683 CmdArgs.push_back(Elt: "-lcrt1.o");
3684 else if (D.isIPhoneOSVersionLT(V0: 6, V1: 0))
3685 CmdArgs.push_back(Elt: "-lcrt1.3.1.o");
3686 return;
3687 }
3688
3689 if (!D.isTargetMacOS())
3690 return;
3691 if (D.isMacosxVersionLT(V0: 10, V1: 5))
3692 CmdArgs.push_back(Elt: "-lcrt1.o");
3693 else if (D.isMacosxVersionLT(V0: 10, V1: 6))
3694 CmdArgs.push_back(Elt: "-lcrt1.10.5.o");
3695 else if (D.isMacosxVersionLT(V0: 10, V1: 8))
3696 CmdArgs.push_back(Elt: "-lcrt1.10.6.o");
3697 // darwin_crt2 spec is empty.
3698}
3699
3700void Darwin::addStartObjectFileArgs(const ArgList &Args,
3701 ArgStringList &CmdArgs) const {
3702 // Derived from startfile spec.
3703 if (Args.hasArg(Ids: options::OPT_dynamiclib))
3704 addDynamicLibLinkArgs(D: *this, Args, CmdArgs);
3705 else if (Args.hasArg(Ids: options::OPT_bundle))
3706 addBundleLinkArgs(D: *this, Args, CmdArgs);
3707 else if (Args.hasArg(Ids: options::OPT_pg) && SupportsProfiling())
3708 addPgProfilingLinkArgs(D: *this, Args, CmdArgs);
3709 else if (Args.hasArg(Ids: options::OPT_static) ||
3710 Args.hasArg(Ids: options::OPT_object) ||
3711 Args.hasArg(Ids: options::OPT_preload))
3712 CmdArgs.push_back(Elt: "-lcrt0.o");
3713 else
3714 addDefaultCRTLinkArgs(D: *this, Args, CmdArgs);
3715
3716 if (isTargetMacOS() && Args.hasArg(Ids: options::OPT_shared_libgcc) &&
3717 isMacosxVersionLT(V0: 10, V1: 5)) {
3718 const char *Str = Args.MakeArgString(Str: GetFilePath(Name: "crt3.o"));
3719 CmdArgs.push_back(Elt: Str);
3720 }
3721}
3722
3723void Darwin::CheckObjCARC() const {
3724 if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||
3725 (isTargetMacOSBased() && !isMacosxVersionLT(V0: 10, V1: 6)))
3726 return;
3727 getDriver().Diag(DiagID: diag::err_arc_unsupported_on_toolchain);
3728}
3729
3730SanitizerMask Darwin::getSupportedSanitizers() const {
3731 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
3732 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
3733 SanitizerMask Res = ToolChain::getSupportedSanitizers();
3734 Res |= SanitizerKind::Address;
3735 Res |= SanitizerKind::PointerCompare;
3736 Res |= SanitizerKind::PointerSubtract;
3737 Res |= SanitizerKind::Realtime;
3738 Res |= SanitizerKind::Leak;
3739 Res |= SanitizerKind::Fuzzer;
3740 Res |= SanitizerKind::FuzzerNoLink;
3741 Res |= SanitizerKind::ObjCCast;
3742
3743 // Prior to 10.9, macOS shipped a version of the C++ standard library without
3744 // C++11 support. The same is true of iOS prior to version 5. These OS'es are
3745 // incompatible with -fsanitize=vptr.
3746 if (!(isTargetMacOSBased() && isMacosxVersionLT(V0: 10, V1: 9)) &&
3747 !(isTargetIPhoneOS() && isIPhoneOSVersionLT(V0: 5, V1: 0)))
3748 Res |= SanitizerKind::Vptr;
3749
3750 if ((IsX86_64 || IsAArch64) &&
3751 (isTargetMacOSBased() || isTargetIOSSimulator() ||
3752 isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
3753 Res |= SanitizerKind::Thread;
3754 }
3755
3756 if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {
3757 Res |= SanitizerKind::Type;
3758 }
3759
3760 if (IsX86_64)
3761 Res |= SanitizerKind::NumericalStability;
3762
3763 return Res;
3764}
3765
3766void AppleMachO::printVerboseInfo(raw_ostream &OS) const {
3767 CudaInstallation->print(OS);
3768 RocmInstallation->print(OS);
3769}
3770