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(options::OPT_mios_version_min_EQ))
87 A->ignoreTargetSpecific();
88 if (T.getOS() == llvm::Triple::WatchOS)
89 for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))
90 A->ignoreTargetSpecific();
91 if (T.getOS() == llvm::Triple::TvOS)
92 for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))
93 A->ignoreTargetSpecific();
94
95 T.setOS(llvm::Triple::UnknownOS);
96 T.setObjectFormat(llvm::Triple::MachO);
97 }
98}
99
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(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(options::OPT_gstabs))
133 CmdArgs.push_back(Elt: "--gstabs");
134 else if (Args.hasArg(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(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(options::OPT_mkernel) ||
147 Args.hasArg(options::OPT_fapple_kext)) &&
148 getMachOToolChain().isKernelStatic()) ||
149 Args.hasArg(options::OPT_static)))
150 CmdArgs.push_back(Elt: "-static");
151
152 Args.AddAllArgValues(Output&: CmdArgs, options::Id0: OPT_Wa_COMMA, options::Id1: 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(options::OPT_O_Group)) {
203 if (A->getOption().matches(options::ID: OPT_O0))
204 return true;
205 if (A->getOption().matches(options::ID: 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(options::OPT_Z_Xlinker__no_demangle))
229 CmdArgs.push_back(Elt: "-demangle");
230
231 if (Args.hasArg(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(options::OPT_fapplication_extension,
238 options::OPT_fno_application_extension, 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, options::Id0: OPT_static);
290 if (!Args.hasArg(options::OPT_static))
291 CmdArgs.push_back(Elt: "-dynamic");
292 if (Args.hasArg(options::OPT_fgnu_runtime)) {
293 // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
294 // here. How do we wish to handle such things?
295 }
296
297 if (!Args.hasArg(options::OPT_dynamiclib)) {
298 AddMachOArch(Args, CmdArgs);
299 // FIXME: Why do this only on this path?
300 Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
301
302 Args.AddLastArg(CmdArgs, options::OPT_bundle);
303 Args.AddAllArgs(Output&: CmdArgs, options::Id0: OPT_bundle__loader);
304 Args.AddAllArgs(Output&: CmdArgs, options::Id0: OPT_client__name);
305
306 Arg *A;
307 if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
308 (A = Args.getLastArg(options::OPT_current__version)) ||
309 (A = Args.getLastArg(options::OPT_install__name)))
310 D.Diag(diag::DiagID: err_drv_argument_only_allowed_with) << A->getAsString(Args)
311 << "-dynamiclib";
312
313 Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
314 Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
315 Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
316 } else {
317 CmdArgs.push_back(Elt: "-dylib");
318
319 Arg *A;
320 if ((A = Args.getLastArg(options::OPT_bundle)) ||
321 (A = Args.getLastArg(options::OPT_bundle__loader)) ||
322 (A = Args.getLastArg(options::OPT_client__name)) ||
323 (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
324 (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
325 (A = Args.getLastArg(options::OPT_private__bundle)))
326 D.Diag(diag::DiagID: err_drv_argument_not_allowed_with) << A->getAsString(Args)
327 << "-dynamiclib";
328
329 Args.AddAllArgsTranslated(Output&: CmdArgs, options::Id0: OPT_compatibility__version,
330 Translation: "-dylib_compatibility_version");
331 Args.AddAllArgsTranslated(Output&: CmdArgs, options::Id0: OPT_current__version,
332 Translation: "-dylib_current_version");
333
334 AddMachOArch(Args, CmdArgs);
335
336 Args.AddAllArgsTranslated(Output&: CmdArgs, options::Id0: OPT_install__name,
337 Translation: "-dylib_install_name");
338 }
339
340 Args.AddLastArg(CmdArgs, options::OPT_all__load);
341 Args.AddAllArgs(Output&: CmdArgs, options::Id0: OPT_allowable__client);
342 Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
343 if (MachOTC.isTargetIOSBased())
344 Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
345 Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
346 Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
347 Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
348 Args.AddLastArg(CmdArgs, options::OPT_dynamic);
349 Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
350 Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
351 Args.AddAllArgs(CmdArgs, options::OPT_force__load);
352 Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
353 Args.AddAllArgs(CmdArgs, options::OPT_image__base);
354 Args.AddAllArgs(CmdArgs, options::OPT_init);
355
356 // Add the deployment target.
357 if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)
358 MachOTC.addPlatformVersionArgs(Args, CmdArgs);
359 else
360 MachOTC.addMinVersionArgs(Args, CmdArgs);
361
362 Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
363 Args.AddLastArg(CmdArgs, options::OPT_multi__module);
364 Args.AddLastArg(CmdArgs, options::OPT_single__module);
365 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
366 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
367
368 if (const Arg *A =
369 Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
370 options::OPT_fno_pie, options::OPT_fno_PIE)) {
371 if (A->getOption().matches(options::OPT_fpie) ||
372 A->getOption().matches(options::OPT_fPIE))
373 CmdArgs.push_back(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(diag::err_drv_bitcode_unsupported_on_toolchain);
391 }
392
393 // If GlobalISel is enabled, pass it through to LLVM.
394 if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
395 options::OPT_fno_global_isel)) {
396 if (A->getOption().matches(options::OPT_fglobal_isel)) {
397 CmdArgs.push_back(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(options::OPT_mkernel) ||
406 Args.hasArg(options::OPT_fapple_kext) ||
407 Args.hasArg(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(CmdArgs, options::OPT_prebind);
413 Args.AddLastArg(CmdArgs, options::OPT_noprebind);
414 Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
415 Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
416 Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
417 Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
418 Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
419 Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
420 Args.AddAllArgs(CmdArgs, options::OPT_segprot);
421 Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
422 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
423 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
424 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
425 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
426 Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
427 Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
428
429 // Give --sysroot= preference, over the Apple specific behavior to also use
430 // --isysroot as the syslibroot.
431 // We check `OPT__sysroot_EQ` directly instead of `getSysRoot` to make sure we
432 // prioritise command line arguments over configuration of `DEFAULT_SYSROOT`.
433 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
434 CmdArgs.push_back(Elt: "-syslibroot");
435 CmdArgs.push_back(Elt: A->getValue());
436 } else if (const Arg *A = Args.getLastArg(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(CmdArgs, options::OPT_twolevel__namespace);
445 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
446 Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
447 Args.AddAllArgs(CmdArgs, options::OPT_undefined);
448 Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
449 Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
450 Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
451 Args.AddAllArgs(CmdArgs, options::OPT_y);
452 Args.AddLastArg(CmdArgs, options::OPT_w);
453 Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
454 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
455 Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
456 Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
457 Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
458 Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
459 Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
460 Args.AddLastArg(CmdArgs, options::OPT_why_load);
461 Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
462 Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
463 Args.AddLastArg(CmdArgs, options::OPT_dylinker);
464 Args.AddLastArg(CmdArgs, options::OPT_Mach);
465
466 if (LinkerIsLLD) {
467 if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
468 SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0
469 ? ""
470 : CSPGOGenerateArg->getValue());
471 llvm::sys::path::append(path&: 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(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(options::OPT_fobjc_link_runtime);
495 return true;
496 }
497 return Args.hasArg(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(options::OPT_arch).size() > 1;
507 bool hasExplicitOutputFile =
508 Args.getLastArg(options::OPT_foptimization_record_file_EQ);
509 if (hasMultipleInvocations && hasExplicitOutputFile) {
510 D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
511 << "-foptimization-record-file";
512 return false;
513 }
514 return true;
515}
516
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(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(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(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(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(options::OPT_moutline, options::OPT_mno_outline)) {
611 if (A->getOption().matches(options::OPT_moutline)) {
612 if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
613 CmdArgs.push_back(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(options::OPT_fcodegen_data_generate_EQ);
634 auto *CodeGenDataUseArg = Args.getLastArg(options::OPT_fcodegen_data_use_EQ);
635
636 // We only allow one of them to be specified.
637 const Driver &D = getToolChain().getDriver();
638 if (CodeGenDataGenArg && CodeGenDataUseArg)
639 D.Diag(diag::err_drv_argument_not_allowed_with)
640 << CodeGenDataGenArg->getAsString(Args)
641 << CodeGenDataUseArg->getAsString(Args);
642
643 // For codegen data gen, the output file is passed to the linker
644 // while a boolean flag is passed to the LLVM backend.
645 if (CodeGenDataGenArg) {
646 CmdArgs.push_back(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(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
668 options::OPT_Z_Flag, options::OPT_u_Group});
669
670 // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
671 // members of static archive libraries which implement Objective-C classes or
672 // categories.
673 if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
674 CmdArgs.push_back(Elt: "-ObjC");
675
676 CmdArgs.push_back(Elt: "-o");
677 CmdArgs.push_back(Elt: Output.getFilename());
678
679 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
680 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
681
682 Args.AddAllArgs(CmdArgs, options::OPT_L);
683
684 AddLinkerInputs(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(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
706 getToolChain().addFortranRuntimeLibraryPath(Args, CmdArgs);
707 getToolChain().addFortranRuntimeLibs(Args, CmdArgs);
708 }
709
710 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
711 addOpenMPRuntime(C, CmdArgs, TC: getToolChain(), Args);
712
713 if (isObjCRuntimeLinked(Args) &&
714 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
715 // We use arclite library for both ARC and subscripting support.
716 getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
717
718 CmdArgs.push_back(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(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(options::OPT_nostdlib, options::OPT_nodefaultlibs);
748 bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
749 if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
750 // link_ssp spec is empty.
751
752 // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
753 // we just want to link the builtins, not the other libs like libSystem.
754 if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
755 getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, 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(options::OPT_pthread);
763 Args.ClaimAllArgs(options::OPT_pthreads);
764 }
765 }
766
767 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
768 // endfile_spec is empty.
769 }
770
771 Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
772 Args.AddAllArgs(CmdArgs, options::OPT_F);
773
774 // -iframework should be forwarded as -F.
775 for (const Arg *A : Args.filtered(options::OPT_iframework))
776 CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
777
778 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
779 if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
780 if (A->getValue() == StringRef("Accelerate")) {
781 CmdArgs.push_back(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(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(options::OPT_g_Group);
840 // and "clang -emit-llvm foo.o -o foo"
841 Args.ClaimAllArgs(options::OPT_emit_llvm);
842 // and for "clang -w foo.o -o foo". Other warning options are already
843 // handled somewhere else.
844 Args.ClaimAllArgs(options::OPT_w);
845 // Silence warnings when linking C code with a C++ '-stdlib' argument.
846 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
847
848 // libtool <options> <output_file> <input_files>
849 ArgStringList CmdArgs;
850 // Create and insert file members with a deterministic index.
851 CmdArgs.push_back(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(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(options::OPT_fuse_lipo_EQ, "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(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(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(string: A->getValue());
1100 assert(NewLinkerVersion == LinkerVersion);
1101#endif
1102 return *LinkerVersion;
1103 }
1104
1105 VersionTuple NewLinkerVersion;
1106 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1107 if (NewLinkerVersion.tryParse(A->getValue()))
1108 getDriver().Diag(diag::err_drv_invalid_version_number)
1109 << A->getAsString(Args);
1110
1111 LinkerVersion = NewLinkerVersion;
1112 return *LinkerVersion;
1113}
1114
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(options::OPT_isysroot))
1264 updated = updatePath(A);
1265
1266 if (!updated) {
1267 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
1268 updatePath(A);
1269 }
1270 }
1271
1272 CmdArgs.push_back(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(P))
1292 getDriver().Diag(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(options::OPT_exported__symbols__list))
1445 return true;
1446 if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
1447 !A->getOption().matches(options::OPT_Xlinker))
1448 continue;
1449 if (A->containsValue(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(options::OPT_rtlib_EQ)) {
1525 StringRef Value = A->getValue();
1526 if (Value != "compiler-rt" && Value != "platform")
1527 getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
1528 << Value << "darwin";
1529 }
1530
1531 return ToolChain::RLT_CompilerRT;
1532}
1533
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(options::OPT_static) ||
1543 Args.hasArg(options::OPT_fapple_kext) ||
1544 Args.hasArg(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(options::OPT_static_libgcc)) {
1554 getDriver().Diag(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(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(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(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 case InferredFromSDK:
1797 case InferredFromArch:
1798 assert(Arg && "OS version argument not yet inferred");
1799 return Arg->getAsString(Args);
1800 case DeploymentTargetEnv:
1801 return (llvm::Twine(EnvVarName) + "=" + OSVersionStr).str();
1802 }
1803 llvm_unreachable("Unsupported Darwin Source Kind");
1804 }
1805
1806 void setEnvironment(llvm::Triple::EnvironmentType EnvType,
1807 const VersionTuple &OSVersion,
1808 const std::optional<DarwinSDKInfo> &SDKInfo) {
1809 switch (EnvType) {
1810 case llvm::Triple::Simulator:
1811 Environment = DarwinEnvironmentKind::Simulator;
1812 break;
1813 case llvm::Triple::MacABI: {
1814 Environment = DarwinEnvironmentKind::MacCatalyst;
1815 // The minimum native macOS target for MacCatalyst is macOS 10.15.
1816 ZipperedOSVersion = VersionTuple(10, 15);
1817 if (hasOSVersion() && SDKInfo) {
1818 if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
1819 Kind: DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
1820 if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
1821 Key: OSVersion, MinimumValue: ZipperedOSVersion, MaximumValue: std::nullopt)) {
1822 ZipperedOSVersion = *MacOSVersion;
1823 }
1824 }
1825 }
1826 // In a zippered build, we could be building for a macOS target that's
1827 // lower than the version that's implied by the OS version. In that case
1828 // we need to use the minimum version as the native target version.
1829 if (TargetVariantTriple) {
1830 auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
1831 if (TargetVariantVersion.getMajor()) {
1832 if (TargetVariantVersion < ZipperedOSVersion)
1833 ZipperedOSVersion = TargetVariantVersion;
1834 }
1835 }
1836 break;
1837 }
1838 default:
1839 break;
1840 }
1841 }
1842
1843 static DarwinPlatform
1844 createFromTarget(const llvm::Triple &TT, Arg *A,
1845 std::optional<llvm::Triple> TargetVariantTriple,
1846 const std::optional<DarwinSDKInfo> &SDKInfo) {
1847 DarwinPlatform Result(TargetArg, getPlatformFromOS(OS: TT.getOS()),
1848 TT.getOSVersion(), A);
1849 VersionTuple OsVersion = TT.getOSVersion();
1850 Result.TargetVariantTriple = TargetVariantTriple;
1851 Result.setEnvironment(EnvType: TT.getEnvironment(), OSVersion: OsVersion, SDKInfo);
1852 return Result;
1853 }
1854 static DarwinPlatform
1855 createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
1856 llvm::Triple::EnvironmentType Environment, Arg *A,
1857 const std::optional<DarwinSDKInfo> &SDKInfo) {
1858 DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS), OSVersion, A);
1859 Result.InferSimulatorFromArch = false;
1860 Result.setEnvironment(EnvType: Environment, OSVersion, SDKInfo);
1861 return Result;
1862 }
1863 static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
1864 bool IsSimulator) {
1865 DarwinPlatform Result{OSVersionArg, Platform,
1866 getVersionFromString(Input: A->getValue()), A};
1867 if (IsSimulator)
1868 Result.Environment = DarwinEnvironmentKind::Simulator;
1869 return Result;
1870 }
1871 static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
1872 StringRef EnvVarName,
1873 StringRef OSVersion) {
1874 DarwinPlatform Result(DeploymentTargetEnv, Platform,
1875 getVersionFromString(Input: OSVersion));
1876 Result.EnvVarName = EnvVarName;
1877 return Result;
1878 }
1879 static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
1880 StringRef Value,
1881 bool IsSimulator = false) {
1882 DarwinPlatform Result(InferredFromSDK, Platform,
1883 getVersionFromString(Input: Value));
1884 if (IsSimulator)
1885 Result.Environment = DarwinEnvironmentKind::Simulator;
1886 Result.InferSimulatorFromArch = false;
1887 return Result;
1888 }
1889 static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
1890 VersionTuple Version) {
1891 return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Version);
1892 }
1893
1894 /// Constructs an inferred SDKInfo value based on the version inferred from
1895 /// the SDK path itself. Only works for values that were created by inferring
1896 /// the platform from the SDKPath.
1897 DarwinSDKInfo inferSDKInfo() {
1898 assert(Kind == InferredFromSDK && "can infer SDK info only");
1899 return DarwinSDKInfo(getOSVersion(),
1900 /*MaximumDeploymentTarget=*/
1901 VersionTuple(getOSVersion().getMajor(), 0, 99),
1902 getOSFromPlatform(Platform));
1903 }
1904
1905private:
1906 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
1907 : Kind(Kind), Platform(Platform),
1908 Arguments({Argument, VersionTuple().getAsString()}) {}
1909 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform,
1910 VersionTuple Value, Arg *Argument = nullptr)
1911 : Kind(Kind), Platform(Platform),
1912 Arguments({Argument, Value.getAsString()}) {
1913 if (!Value.empty())
1914 UnderlyingOSVersion = Value;
1915 }
1916
1917 static VersionTuple getVersionFromString(const StringRef Input) {
1918 llvm::VersionTuple Version;
1919 bool IsValid = !Version.tryParse(string: Input);
1920 assert(IsValid && "unable to convert input version to version tuple");
1921 (void)IsValid;
1922 return Version;
1923 }
1924
1925 static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
1926 switch (OS) {
1927 case llvm::Triple::Darwin:
1928 case llvm::Triple::MacOSX:
1929 return DarwinPlatformKind::MacOS;
1930 case llvm::Triple::IOS:
1931 return DarwinPlatformKind::IPhoneOS;
1932 case llvm::Triple::TvOS:
1933 return DarwinPlatformKind::TvOS;
1934 case llvm::Triple::WatchOS:
1935 return DarwinPlatformKind::WatchOS;
1936 case llvm::Triple::XROS:
1937 return DarwinPlatformKind::XROS;
1938 case llvm::Triple::DriverKit:
1939 return DarwinPlatformKind::DriverKit;
1940 default:
1941 llvm_unreachable("Unable to infer Darwin variant");
1942 }
1943 }
1944
1945 static llvm::Triple::OSType getOSFromPlatform(DarwinPlatformKind Platform) {
1946 switch (Platform) {
1947 case DarwinPlatformKind::MacOS:
1948 return llvm::Triple::MacOSX;
1949 case DarwinPlatformKind::IPhoneOS:
1950 return llvm::Triple::IOS;
1951 case DarwinPlatformKind::TvOS:
1952 return llvm::Triple::TvOS;
1953 case DarwinPlatformKind::WatchOS:
1954 return llvm::Triple::WatchOS;
1955 case DarwinPlatformKind::DriverKit:
1956 return llvm::Triple::DriverKit;
1957 case DarwinPlatformKind::XROS:
1958 return llvm::Triple::XROS;
1959 }
1960 llvm_unreachable("Unknown DarwinPlatformKind enum");
1961 }
1962
1963 SourceKind Kind;
1964 DarwinPlatformKind Platform;
1965 DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
1966 // When compiling for a zippered target, this means both target &
1967 // target variant is set on the command line, ZipperedOSVersion holds the
1968 // OSVersion tied to the main target value.
1969 VersionTuple ZipperedOSVersion;
1970 // We allow multiple ways to set or default the OS
1971 // version used for compilation. When set, UnderlyingOSVersion represents
1972 // the intended version to match the platform information computed from
1973 // arguments.
1974 std::optional<VersionTuple> UnderlyingOSVersion;
1975 bool InferSimulatorFromArch = true;
1976 std::pair<Arg *, std::string> Arguments;
1977 StringRef EnvVarName;
1978 // When compiling for a zippered target, this value represents the target
1979 // triple encoded in the target variant.
1980 std::optional<llvm::Triple> TargetVariantTriple;
1981};
1982
1983/// Returns the deployment target that's specified using the -m<os>-version-min
1984/// argument.
1985std::optional<DarwinPlatform>
1986getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
1987 const Driver &TheDriver) {
1988 Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
1989 Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
1990 options::OPT_mios_simulator_version_min_EQ);
1991 Arg *TvOSVersion =
1992 Args.getLastArg(options::OPT_mtvos_version_min_EQ,
1993 options::OPT_mtvos_simulator_version_min_EQ);
1994 Arg *WatchOSVersion =
1995 Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
1996 options::OPT_mwatchos_simulator_version_min_EQ);
1997
1998 auto GetDarwinPlatform =
1999 [&](DarwinPlatform::DarwinPlatformKind Platform, Arg *VersionArg,
2000 bool IsSimulator) -> std::optional<DarwinPlatform> {
2001 if (StringRef(VersionArg->getValue()).empty()) {
2002 TheDriver.Diag(diag::err_drv_missing_version_number)
2003 << VersionArg->getAsString(Args);
2004 return std::nullopt;
2005 }
2006 return DarwinPlatform::createOSVersionArg(Platform, A: VersionArg,
2007 /*IsSimulator=*/IsSimulator);
2008 };
2009
2010 if (macOSVersion) {
2011 if (iOSVersion || TvOSVersion || WatchOSVersion) {
2012 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
2013 << macOSVersion->getAsString(Args)
2014 << (iOSVersion ? iOSVersion
2015 : TvOSVersion ? TvOSVersion : WatchOSVersion)
2016 ->getAsString(Args);
2017 }
2018 return GetDarwinPlatform(Darwin::MacOS, macOSVersion,
2019 /*IsSimulator=*/false);
2020
2021 } else if (iOSVersion) {
2022 if (TvOSVersion || WatchOSVersion) {
2023 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
2024 << iOSVersion->getAsString(Args)
2025 << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
2026 }
2027 return GetDarwinPlatform(Darwin::IPhoneOS, iOSVersion,
2028 iOSVersion->getOption().getID() ==
2029 options::OPT_mios_simulator_version_min_EQ);
2030 } else if (TvOSVersion) {
2031 if (WatchOSVersion) {
2032 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
2033 << TvOSVersion->getAsString(Args)
2034 << WatchOSVersion->getAsString(Args);
2035 }
2036 return GetDarwinPlatform(Darwin::TvOS, TvOSVersion,
2037 TvOSVersion->getOption().getID() ==
2038 options::OPT_mtvos_simulator_version_min_EQ);
2039 } else if (WatchOSVersion)
2040 return GetDarwinPlatform(
2041 Darwin::WatchOS, WatchOSVersion,
2042 WatchOSVersion->getOption().getID() ==
2043 options::OPT_mwatchos_simulator_version_min_EQ);
2044 return std::nullopt;
2045}
2046
2047/// Returns the deployment target that's specified using the
2048/// OS_DEPLOYMENT_TARGET environment variable.
2049std::optional<DarwinPlatform>
2050getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
2051 const llvm::Triple &Triple) {
2052 std::string Targets[Darwin::LastDarwinPlatform + 1];
2053 const char *EnvVars[] = {
2054 "MACOSX_DEPLOYMENT_TARGET",
2055 "IPHONEOS_DEPLOYMENT_TARGET",
2056 "TVOS_DEPLOYMENT_TARGET",
2057 "WATCHOS_DEPLOYMENT_TARGET",
2058 "DRIVERKIT_DEPLOYMENT_TARGET",
2059 "XROS_DEPLOYMENT_TARGET"
2060 };
2061 static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,
2062 "Missing platform");
2063 for (const auto &I : llvm::enumerate(First: llvm::ArrayRef(EnvVars))) {
2064 if (char *Env = ::getenv(name: I.value()))
2065 Targets[I.index()] = Env;
2066 }
2067
2068 // Allow conflicts among OSX and iOS for historical reasons, but choose the
2069 // default platform.
2070 if (!Targets[Darwin::MacOS].empty() &&
2071 (!Targets[Darwin::IPhoneOS].empty() ||
2072 !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() ||
2073 !Targets[Darwin::XROS].empty())) {
2074 if (Triple.getArch() == llvm::Triple::arm ||
2075 Triple.getArch() == llvm::Triple::aarch64 ||
2076 Triple.getArch() == llvm::Triple::thumb)
2077 Targets[Darwin::MacOS] = "";
2078 else
2079 Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
2080 Targets[Darwin::TvOS] = Targets[Darwin::XROS] = "";
2081 } else {
2082 // Don't allow conflicts in any other platform.
2083 unsigned FirstTarget = std::size(Targets);
2084 for (unsigned I = 0; I != std::size(Targets); ++I) {
2085 if (Targets[I].empty())
2086 continue;
2087 if (FirstTarget == std::size(Targets))
2088 FirstTarget = I;
2089 else
2090 TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
2091 << Targets[FirstTarget] << Targets[I];
2092 }
2093 }
2094
2095 for (const auto &Target : llvm::enumerate(First: llvm::ArrayRef(Targets))) {
2096 if (!Target.value().empty())
2097 return DarwinPlatform::createDeploymentTargetEnv(
2098 Platform: (Darwin::DarwinPlatformKind)Target.index(), EnvVarName: EnvVars[Target.index()],
2099 OSVersion: Target.value());
2100 }
2101 return std::nullopt;
2102}
2103
2104/// Returns the SDK name without the optional prefix that ends with a '.' or an
2105/// empty string otherwise.
2106static StringRef dropSDKNamePrefix(StringRef SDKName) {
2107 size_t PrefixPos = SDKName.find(C: '.');
2108 if (PrefixPos == StringRef::npos)
2109 return "";
2110 return SDKName.substr(Start: PrefixPos + 1);
2111}
2112
2113/// Tries to infer the deployment target from the SDK specified by -isysroot
2114/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
2115/// it's available.
2116std::optional<DarwinPlatform>
2117inferDeploymentTargetFromSDK(DerivedArgList &Args,
2118 const std::optional<DarwinSDKInfo> &SDKInfo) {
2119 const Arg *A = Args.getLastArg(options::OPT_isysroot);
2120 if (!A)
2121 return std::nullopt;
2122 StringRef isysroot = A->getValue();
2123 StringRef SDK = Darwin::getSDKName(isysroot);
2124 if (!SDK.size())
2125 return std::nullopt;
2126
2127 std::string Version;
2128 if (SDKInfo) {
2129 // Get the version from the SDKSettings.json if it's available.
2130 Version = SDKInfo->getVersion().getAsString();
2131 } else {
2132 // Slice the version number out.
2133 // Version number is between the first and the last number.
2134 size_t StartVer = SDK.find_first_of(Chars: "0123456789");
2135 size_t EndVer = SDK.find_last_of(Chars: "0123456789");
2136 if (StartVer != StringRef::npos && EndVer > StartVer)
2137 Version = std::string(SDK.slice(Start: StartVer, End: EndVer + 1));
2138 }
2139 if (Version.empty())
2140 return std::nullopt;
2141
2142 auto CreatePlatformFromSDKName =
2143 [&](StringRef SDK) -> std::optional<DarwinPlatform> {
2144 if (SDK.starts_with(Prefix: "iPhoneOS") || SDK.starts_with(Prefix: "iPhoneSimulator"))
2145 return DarwinPlatform::createFromSDK(
2146 Platform: Darwin::IPhoneOS, Value: Version,
2147 /*IsSimulator=*/SDK.starts_with(Prefix: "iPhoneSimulator"));
2148 else if (SDK.starts_with(Prefix: "MacOSX"))
2149 return DarwinPlatform::createFromSDK(Platform: Darwin::MacOS,
2150 Value: getSystemOrSDKMacOSVersion(MacOSSDKVersion: Version));
2151 else if (SDK.starts_with(Prefix: "WatchOS") || SDK.starts_with(Prefix: "WatchSimulator"))
2152 return DarwinPlatform::createFromSDK(
2153 Platform: Darwin::WatchOS, Value: Version,
2154 /*IsSimulator=*/SDK.starts_with(Prefix: "WatchSimulator"));
2155 else if (SDK.starts_with(Prefix: "AppleTVOS") ||
2156 SDK.starts_with(Prefix: "AppleTVSimulator"))
2157 return DarwinPlatform::createFromSDK(
2158 Platform: Darwin::TvOS, Value: Version,
2159 /*IsSimulator=*/SDK.starts_with(Prefix: "AppleTVSimulator"));
2160 else if (SDK.starts_with(Prefix: "XR"))
2161 return DarwinPlatform::createFromSDK(
2162 Platform: Darwin::XROS, Value: Version,
2163 /*IsSimulator=*/SDK.contains(Other: "Simulator"));
2164 else if (SDK.starts_with(Prefix: "DriverKit"))
2165 return DarwinPlatform::createFromSDK(Platform: Darwin::DriverKit, Value: Version);
2166 return std::nullopt;
2167 };
2168 if (auto Result = CreatePlatformFromSDKName(SDK))
2169 return Result;
2170 // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
2171 return CreatePlatformFromSDKName(dropSDKNamePrefix(SDKName: SDK));
2172}
2173// Compute & get the OS Version when the target triple omitted one.
2174VersionTuple getInferredOSVersion(llvm::Triple::OSType OS,
2175 const llvm::Triple &Triple,
2176 const Driver &TheDriver) {
2177 VersionTuple OsVersion;
2178 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
2179 switch (OS) {
2180 case llvm::Triple::Darwin:
2181 case llvm::Triple::MacOSX:
2182 // If there is no version specified on triple, and both host and target are
2183 // macos, use the host triple to infer OS version.
2184 if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
2185 !Triple.getOSMajorVersion())
2186 SystemTriple.getMacOSXVersion(Version&: OsVersion);
2187 else if (!Triple.getMacOSXVersion(OsVersion))
2188 TheDriver.Diag(diag::err_drv_invalid_darwin_version)
2189 << Triple.getOSName();
2190 break;
2191 case llvm::Triple::IOS:
2192 if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
2193 OsVersion = VersionTuple(13, 1);
2194 } else
2195 OsVersion = Triple.getiOSVersion();
2196 break;
2197 case llvm::Triple::TvOS:
2198 OsVersion = Triple.getOSVersion();
2199 break;
2200 case llvm::Triple::WatchOS:
2201 OsVersion = Triple.getWatchOSVersion();
2202 break;
2203 case llvm::Triple::XROS:
2204 OsVersion = Triple.getOSVersion();
2205 if (!OsVersion.getMajor())
2206 OsVersion = OsVersion.withMajorReplaced(NewMajor: 1);
2207 break;
2208 case llvm::Triple::DriverKit:
2209 OsVersion = Triple.getDriverKitVersion();
2210 break;
2211 default:
2212 llvm_unreachable("Unexpected OS type");
2213 break;
2214 }
2215 return OsVersion;
2216}
2217
2218/// Tries to infer the target OS from the -arch.
2219std::optional<DarwinPlatform>
2220inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
2221 const llvm::Triple &Triple,
2222 const Driver &TheDriver) {
2223 llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
2224
2225 StringRef MachOArchName = Toolchain.getMachOArchName(Args);
2226 if (MachOArchName == "arm64" || MachOArchName == "arm64e")
2227 OSTy = llvm::Triple::MacOSX;
2228 else if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
2229 MachOArchName == "armv6")
2230 OSTy = llvm::Triple::IOS;
2231 else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
2232 OSTy = llvm::Triple::WatchOS;
2233 else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
2234 MachOArchName != "armv7em")
2235 OSTy = llvm::Triple::MacOSX;
2236 if (OSTy == llvm::Triple::UnknownOS)
2237 return std::nullopt;
2238 return DarwinPlatform::createFromArch(
2239 OS: OSTy, Version: getInferredOSVersion(OS: OSTy, Triple, TheDriver));
2240}
2241
2242/// Returns the deployment target that's specified using the -target option.
2243std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
2244 DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
2245 const std::optional<DarwinSDKInfo> &SDKInfo) {
2246 if (!Args.hasArg(options::OPT_target))
2247 return std::nullopt;
2248 if (Triple.getOS() == llvm::Triple::Darwin ||
2249 Triple.getOS() == llvm::Triple::UnknownOS)
2250 return std::nullopt;
2251 std::optional<llvm::Triple> TargetVariantTriple;
2252 for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
2253 llvm::Triple TVT(A->getValue());
2254 // Find a matching <arch>-<vendor> target variant triple that can be used.
2255 if ((Triple.getArch() == llvm::Triple::aarch64 ||
2256 TVT.getArchName() == Triple.getArchName()) &&
2257 TVT.getArch() == Triple.getArch() &&
2258 TVT.getSubArch() == Triple.getSubArch() &&
2259 TVT.getVendor() == Triple.getVendor()) {
2260 if (TargetVariantTriple)
2261 continue;
2262 A->claim();
2263 // Accept a -target-variant triple when compiling code that may run on
2264 // macOS or Mac Catalyst.
2265 if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
2266 TVT.isMacCatalystEnvironment()) ||
2267 (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
2268 Triple.isMacCatalystEnvironment())) {
2269 TargetVariantTriple = TVT;
2270 continue;
2271 }
2272 TheDriver.Diag(diag::err_drv_target_variant_invalid)
2273 << A->getSpelling() << A->getValue();
2274 }
2275 }
2276 DarwinPlatform PlatformAndVersion = DarwinPlatform::createFromTarget(
2277 Triple, Args.getLastArg(options::OPT_target), TargetVariantTriple,
2278 SDKInfo);
2279
2280 return PlatformAndVersion;
2281}
2282
2283/// Returns the deployment target that's specified using the -mtargetos option.
2284std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
2285 DerivedArgList &Args, const Driver &TheDriver,
2286 const std::optional<DarwinSDKInfo> &SDKInfo) {
2287 auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
2288 if (!A)
2289 return std::nullopt;
2290 llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
2291 switch (TT.getOS()) {
2292 case llvm::Triple::MacOSX:
2293 case llvm::Triple::IOS:
2294 case llvm::Triple::TvOS:
2295 case llvm::Triple::WatchOS:
2296 case llvm::Triple::XROS:
2297 break;
2298 default:
2299 TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
2300 << TT.getOSName() << A->getAsString(Args);
2301 return std::nullopt;
2302 }
2303
2304 VersionTuple Version = TT.getOSVersion();
2305 if (!Version.getMajor()) {
2306 TheDriver.Diag(diag::err_drv_invalid_version_number)
2307 << A->getAsString(Args);
2308 return std::nullopt;
2309 }
2310 return DarwinPlatform::createFromMTargetOS(OS: TT.getOS(), OSVersion: Version,
2311 Environment: TT.getEnvironment(), A: A, SDKInfo);
2312}
2313
2314std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
2315 const ArgList &Args,
2316 const Driver &TheDriver) {
2317 const Arg *A = Args.getLastArg(options::OPT_isysroot);
2318 if (!A)
2319 return std::nullopt;
2320 StringRef isysroot = A->getValue();
2321 auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, SDKRootPath: isysroot);
2322 if (!SDKInfoOrErr) {
2323 llvm::consumeError(Err: SDKInfoOrErr.takeError());
2324 TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
2325 return std::nullopt;
2326 }
2327 return *SDKInfoOrErr;
2328}
2329
2330} // namespace
2331
2332void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
2333 const OptTable &Opts = getDriver().getOpts();
2334
2335 // Support allowing the SDKROOT environment variable used by xcrun and other
2336 // Xcode tools to define the default sysroot, by making it the default for
2337 // isysroot.
2338 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2339 // Warn if the path does not exist.
2340 if (!getVFS().exists(A->getValue()))
2341 getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
2342 } else {
2343 if (char *env = ::getenv(name: "SDKROOT")) {
2344 // We only use this value as the default if it is an absolute path,
2345 // exists, and it is not the root path.
2346 if (llvm::sys::path::is_absolute(path: env) && getVFS().exists(Path: env) &&
2347 StringRef(env) != "/") {
2348 Args.append(Args.MakeSeparateArg(
2349 nullptr, Opts.getOption(options::OPT_isysroot), env));
2350 }
2351 }
2352 }
2353
2354 // Read the SDKSettings.json file for more information, like the SDK version
2355 // that we can pass down to the compiler.
2356 SDKInfo = parseSDKSettings(VFS&: getVFS(), Args, TheDriver: getDriver());
2357
2358 // The OS and the version can be specified using the -target argument.
2359 std::optional<DarwinPlatform> PlatformAndVersion =
2360 getDeploymentTargetFromTargetArg(Args, Triple: getTriple(), TheDriver: getDriver(), SDKInfo);
2361 if (PlatformAndVersion) {
2362 // Disallow mixing -target and -mtargetos=.
2363 if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
2364 std::string TargetArgStr = PlatformAndVersion->getAsString(Args, Opts);
2365 std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
2366 getDriver().Diag(diag::err_drv_cannot_mix_options)
2367 << TargetArgStr << MTargetOSArgStr;
2368 }
2369 // Implicitly allow resolving the OS version when it wasn't explicitly set.
2370 bool TripleProvidedOSVersion = PlatformAndVersion->hasOSVersion();
2371 if (!TripleProvidedOSVersion)
2372 PlatformAndVersion->setOSVersion(
2373 getInferredOSVersion(OS: getTriple().getOS(), Triple: getTriple(), TheDriver: getDriver()));
2374
2375 std::optional<DarwinPlatform> PlatformAndVersionFromOSVersionArg =
2376 getDeploymentTargetFromOSVersionArg(Args, TheDriver: getDriver());
2377 if (PlatformAndVersionFromOSVersionArg) {
2378 unsigned TargetMajor, TargetMinor, TargetMicro;
2379 bool TargetExtra;
2380 unsigned ArgMajor, ArgMinor, ArgMicro;
2381 bool ArgExtra;
2382 if (PlatformAndVersion->getPlatform() !=
2383 PlatformAndVersionFromOSVersionArg->getPlatform() ||
2384 (Driver::GetReleaseVersion(
2385 Str: PlatformAndVersion->getOSVersion().getAsString(), Major&: TargetMajor,
2386 Minor&: TargetMinor, Micro&: TargetMicro, HadExtra&: TargetExtra) &&
2387 Driver::GetReleaseVersion(
2388 Str: PlatformAndVersionFromOSVersionArg->getOSVersion().getAsString(),
2389 Major&: ArgMajor, Minor&: ArgMinor, Micro&: ArgMicro, HadExtra&: ArgExtra) &&
2390 (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
2391 VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
2392 TargetExtra != ArgExtra))) {
2393 // Select the OS version from the -m<os>-version-min argument when
2394 // the -target does not include an OS version.
2395 if (PlatformAndVersion->getPlatform() ==
2396 PlatformAndVersionFromOSVersionArg->getPlatform() &&
2397 !TripleProvidedOSVersion) {
2398 PlatformAndVersion->setOSVersion(
2399 PlatformAndVersionFromOSVersionArg->getOSVersion());
2400 } else {
2401 // Warn about -m<os>-version-min that doesn't match the OS version
2402 // that's specified in the target.
2403 std::string OSVersionArg =
2404 PlatformAndVersionFromOSVersionArg->getAsString(Args, Opts);
2405 std::string TargetArg = PlatformAndVersion->getAsString(Args, Opts);
2406 getDriver().Diag(clang::diag::warn_drv_overriding_option)
2407 << OSVersionArg << TargetArg;
2408 }
2409 }
2410 }
2411 } else if ((PlatformAndVersion = getDeploymentTargetFromMTargetOSArg(
2412 Args, TheDriver: getDriver(), SDKInfo))) {
2413 // The OS target can be specified using the -mtargetos= argument.
2414 // Disallow mixing -mtargetos= and -m<os>version-min=.
2415 std::optional<DarwinPlatform> PlatformAndVersionFromOSVersionArg =
2416 getDeploymentTargetFromOSVersionArg(Args, TheDriver: getDriver());
2417 if (PlatformAndVersionFromOSVersionArg) {
2418 std::string MTargetOSArgStr = PlatformAndVersion->getAsString(Args, Opts);
2419 std::string OSVersionArgStr =
2420 PlatformAndVersionFromOSVersionArg->getAsString(Args, Opts);
2421 getDriver().Diag(diag::err_drv_cannot_mix_options)
2422 << MTargetOSArgStr << OSVersionArgStr;
2423 }
2424 } else {
2425 // The OS target can be specified using the -m<os>version-min argument.
2426 PlatformAndVersion = getDeploymentTargetFromOSVersionArg(Args, TheDriver: getDriver());
2427 // If no deployment target was specified on the command line, check for
2428 // environment defines.
2429 if (!PlatformAndVersion) {
2430 PlatformAndVersion =
2431 getDeploymentTargetFromEnvironmentVariables(TheDriver: getDriver(), Triple: getTriple());
2432 if (PlatformAndVersion) {
2433 // Don't infer simulator from the arch when the SDK is also specified.
2434 std::optional<DarwinPlatform> SDKTarget =
2435 inferDeploymentTargetFromSDK(Args, SDKInfo);
2436 if (SDKTarget)
2437 PlatformAndVersion->setEnvironment(SDKTarget->getEnvironment());
2438 }
2439 }
2440 // If there is no command-line argument to specify the Target version and
2441 // no environment variable defined, see if we can set the default based
2442 // on -isysroot using SDKSettings.json if it exists.
2443 if (!PlatformAndVersion) {
2444 PlatformAndVersion = inferDeploymentTargetFromSDK(Args, SDKInfo);
2445 /// If the target was successfully constructed from the SDK path, try to
2446 /// infer the SDK info if the SDK doesn't have it.
2447 if (PlatformAndVersion && !SDKInfo)
2448 SDKInfo = PlatformAndVersion->inferSDKInfo();
2449 }
2450 // If no OS targets have been specified, try to guess platform from -target
2451 // or arch name and compute the version from the triple.
2452 if (!PlatformAndVersion)
2453 PlatformAndVersion =
2454 inferDeploymentTargetFromArch(Args, Toolchain: *this, Triple: getTriple(), TheDriver: getDriver());
2455 }
2456
2457 assert(PlatformAndVersion && "Unable to infer Darwin variant");
2458 if (!PlatformAndVersion->isValidOSVersion())
2459 getDriver().Diag(diag::err_drv_invalid_version_number)
2460 << PlatformAndVersion->getAsString(Args, Opts);
2461 // After the deployment OS version has been resolved, set it to the canonical
2462 // version before further error detection and converting to a proper target
2463 // triple.
2464 VersionTuple CanonicalVersion = PlatformAndVersion->getCanonicalOSVersion();
2465 if (CanonicalVersion != PlatformAndVersion->getOSVersion()) {
2466 getDriver().Diag(diag::warn_drv_overriding_deployment_version)
2467 << PlatformAndVersion->getOSVersion().getAsString()
2468 << CanonicalVersion.getAsString();
2469 PlatformAndVersion->setOSVersion(CanonicalVersion);
2470 }
2471
2472 PlatformAndVersion->addOSVersionMinArgument(Args, Opts);
2473 DarwinPlatformKind Platform = PlatformAndVersion->getPlatform();
2474
2475 unsigned Major, Minor, Micro;
2476 bool HadExtra;
2477 // The major version should not be over this number.
2478 const unsigned MajorVersionLimit = 1000;
2479 const VersionTuple OSVersion = PlatformAndVersion->takeOSVersion();
2480 const std::string OSVersionStr = OSVersion.getAsString();
2481 // Set the tool chain target information.
2482 if (Platform == MacOS) {
2483 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,
2484 HadExtra) ||
2485 HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
2486 Micro >= 100)
2487 getDriver().Diag(diag::err_drv_invalid_version_number)
2488 << PlatformAndVersion->getAsString(Args, Opts);
2489 } else if (Platform == IPhoneOS) {
2490 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,
2491 HadExtra) ||
2492 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2493 getDriver().Diag(diag::err_drv_invalid_version_number)
2494 << PlatformAndVersion->getAsString(Args, Opts);
2495 ;
2496 if (PlatformAndVersion->getEnvironment() == MacCatalyst &&
2497 (Major < 13 || (Major == 13 && Minor < 1))) {
2498 getDriver().Diag(diag::err_drv_invalid_version_number)
2499 << PlatformAndVersion->getAsString(Args, Opts);
2500 Major = 13;
2501 Minor = 1;
2502 Micro = 0;
2503 }
2504 // For 32-bit targets, the deployment target for iOS has to be earlier than
2505 // iOS 11.
2506 if (getTriple().isArch32Bit() && Major >= 11) {
2507 // If the deployment target is explicitly specified, print a diagnostic.
2508 if (PlatformAndVersion->isExplicitlySpecified()) {
2509 if (PlatformAndVersion->getEnvironment() == MacCatalyst)
2510 getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
2511 else
2512 getDriver().Diag(diag::warn_invalid_ios_deployment_target)
2513 << PlatformAndVersion->getAsString(Args, Opts);
2514 // Otherwise, set it to 10.99.99.
2515 } else {
2516 Major = 10;
2517 Minor = 99;
2518 Micro = 99;
2519 }
2520 }
2521 } else if (Platform == TvOS) {
2522 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,
2523 HadExtra) ||
2524 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2525 getDriver().Diag(diag::err_drv_invalid_version_number)
2526 << PlatformAndVersion->getAsString(Args, Opts);
2527 } else if (Platform == WatchOS) {
2528 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,
2529 HadExtra) ||
2530 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2531 getDriver().Diag(diag::err_drv_invalid_version_number)
2532 << PlatformAndVersion->getAsString(Args, Opts);
2533 } else if (Platform == DriverKit) {
2534 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,
2535 HadExtra) ||
2536 HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
2537 Micro >= 100)
2538 getDriver().Diag(diag::err_drv_invalid_version_number)
2539 << PlatformAndVersion->getAsString(Args, Opts);
2540 } else if (Platform == XROS) {
2541 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,
2542 HadExtra) ||
2543 HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
2544 Micro >= 100)
2545 getDriver().Diag(diag::err_drv_invalid_version_number)
2546 << PlatformAndVersion->getAsString(Args, Opts);
2547 } else
2548 llvm_unreachable("unknown kind of Darwin platform");
2549
2550 DarwinEnvironmentKind Environment = PlatformAndVersion->getEnvironment();
2551 // Recognize iOS targets with an x86 architecture as the iOS simulator.
2552 if (Environment == NativeEnvironment && Platform != MacOS &&
2553 Platform != DriverKit &&
2554 PlatformAndVersion->canInferSimulatorFromArch() && getTriple().isX86())
2555 Environment = Simulator;
2556
2557 VersionTuple ZipperedOSVersion;
2558 if (Environment == MacCatalyst)
2559 ZipperedOSVersion = PlatformAndVersion->getZipperedOSVersion();
2560 setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion: ZipperedOSVersion);
2561 TargetVariantTriple = PlatformAndVersion->getTargetVariantTriple();
2562 if (TargetVariantTriple &&
2563 !llvm::Triple::isValidVersionForOS(OSKind: TargetVariantTriple->getOS(),
2564 Version: TargetVariantTriple->getOSVersion())) {
2565 getDriver().Diag(diag::err_drv_invalid_version_number)
2566 << TargetVariantTriple->str();
2567 }
2568
2569 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2570 StringRef SDK = getSDKName(isysroot: A->getValue());
2571 if (SDK.size() > 0) {
2572 size_t StartVer = SDK.find_first_of(Chars: "0123456789");
2573 StringRef SDKName = SDK.slice(Start: 0, End: StartVer);
2574 if (!SDKName.starts_with(getPlatformFamily()) &&
2575 !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))
2576 getDriver().Diag(diag::warn_incompatible_sysroot)
2577 << SDKName << getPlatformFamily();
2578 }
2579 }
2580}
2581
2582// For certain platforms/environments almost all resources (e.g., headers) are
2583// located in sub-directories, e.g., for DriverKit they live in
2584// <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).
2585static void AppendPlatformPrefix(SmallString<128> &Path,
2586 const llvm::Triple &T) {
2587 if (T.isDriverKit()) {
2588 llvm::sys::path::append(path&: Path, a: "System", b: "DriverKit");
2589 }
2590}
2591
2592// Returns the effective sysroot from either -isysroot or --sysroot, plus the
2593// platform prefix (if any).
2594llvm::SmallString<128>
2595AppleMachO::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2596 llvm::SmallString<128> Path("/");
2597 if (DriverArgs.hasArg(options::OPT_isysroot))
2598 Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
2599 else if (!getDriver().SysRoot.empty())
2600 Path = getDriver().SysRoot;
2601
2602 if (hasEffectiveTriple()) {
2603 AppendPlatformPrefix(Path, T: getEffectiveTriple());
2604 }
2605 return Path;
2606}
2607
2608void AppleMachO::AddClangSystemIncludeArgs(
2609 const llvm::opt::ArgList &DriverArgs,
2610 llvm::opt::ArgStringList &CC1Args) const {
2611 const Driver &D = getDriver();
2612
2613 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2614
2615 bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
2616 bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
2617 bool NoBuiltinInc = DriverArgs.hasFlag(
2618 options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
2619 bool ForceBuiltinInc = DriverArgs.hasFlag(
2620 options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
2621
2622 // Add <sysroot>/usr/local/include
2623 if (!NoStdInc && !NoStdlibInc) {
2624 SmallString<128> P(Sysroot);
2625 llvm::sys::path::append(path&: P, a: "usr", b: "local", c: "include");
2626 addSystemInclude(DriverArgs, CC1Args, Path: P);
2627 }
2628
2629 // Add the Clang builtin headers (<resource>/include)
2630 if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
2631 SmallString<128> P(D.ResourceDir);
2632 llvm::sys::path::append(path&: P, a: "include");
2633 addSystemInclude(DriverArgs, CC1Args, Path: P);
2634 }
2635
2636 if (NoStdInc || NoStdlibInc)
2637 return;
2638
2639 // Check for configure-time C include directories.
2640 llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
2641 if (!CIncludeDirs.empty()) {
2642 llvm::SmallVector<llvm::StringRef, 5> dirs;
2643 CIncludeDirs.split(A&: dirs, Separator: ":");
2644 for (llvm::StringRef dir : dirs) {
2645 llvm::StringRef Prefix =
2646 llvm::sys::path::is_absolute(path: dir) ? "" : llvm::StringRef(Sysroot);
2647 addExternCSystemInclude(DriverArgs, CC1Args, Path: Prefix + dir);
2648 }
2649 } else {
2650 // Otherwise, add <sysroot>/usr/include.
2651 SmallString<128> P(Sysroot);
2652 llvm::sys::path::append(path&: P, a: "usr", b: "include");
2653 addExternCSystemInclude(DriverArgs, CC1Args, Path: P.str());
2654 }
2655}
2656
2657void DarwinClang::AddClangSystemIncludeArgs(
2658 const llvm::opt::ArgList &DriverArgs,
2659 llvm::opt::ArgStringList &CC1Args) const {
2660 AppleMachO::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
2661
2662 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc))
2663 return;
2664
2665 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2666
2667 // Add <sysroot>/System/Library/Frameworks
2668 // Add <sysroot>/System/Library/SubFrameworks
2669 // Add <sysroot>/Library/Frameworks
2670 SmallString<128> P1(Sysroot), P2(Sysroot), P3(Sysroot);
2671 llvm::sys::path::append(path&: P1, a: "System", b: "Library", c: "Frameworks");
2672 llvm::sys::path::append(path&: P2, a: "System", b: "Library", c: "SubFrameworks");
2673 llvm::sys::path::append(path&: P3, a: "Library", b: "Frameworks");
2674 addSystemFrameworkIncludes(DriverArgs, CC1Args, Paths: {P1, P2, P3});
2675}
2676
2677bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
2678 llvm::opt::ArgStringList &CC1Args,
2679 llvm::SmallString<128> Base,
2680 llvm::StringRef Version,
2681 llvm::StringRef ArchDir,
2682 llvm::StringRef BitDir) const {
2683 llvm::sys::path::append(path&: Base, a: Version);
2684
2685 // Add the base dir
2686 addSystemInclude(DriverArgs, CC1Args, Path: Base);
2687
2688 // Add the multilib dirs
2689 {
2690 llvm::SmallString<128> P = Base;
2691 if (!ArchDir.empty())
2692 llvm::sys::path::append(path&: P, a: ArchDir);
2693 if (!BitDir.empty())
2694 llvm::sys::path::append(path&: P, a: BitDir);
2695 addSystemInclude(DriverArgs, CC1Args, Path: P);
2696 }
2697
2698 // Add the backward dir
2699 {
2700 llvm::SmallString<128> P = Base;
2701 llvm::sys::path::append(path&: P, a: "backward");
2702 addSystemInclude(DriverArgs, CC1Args, Path: P);
2703 }
2704
2705 return getVFS().exists(Path: Base);
2706}
2707
2708void AppleMachO::AddClangCXXStdlibIncludeArgs(
2709 const llvm::opt::ArgList &DriverArgs,
2710 llvm::opt::ArgStringList &CC1Args) const {
2711 // The implementation from a base class will pass through the -stdlib to
2712 // CC1Args.
2713 // FIXME: this should not be necessary, remove usages in the frontend
2714 // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
2715 // Also check whether this is used for setting library search paths.
2716 ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
2717
2718 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
2719 options::OPT_nostdincxx))
2720 return;
2721
2722 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2723
2724 switch (GetCXXStdlibType(Args: DriverArgs)) {
2725 case ToolChain::CST_Libcxx: {
2726 // On Darwin, libc++ can be installed in one of the following places:
2727 // 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
2728 // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
2729 //
2730 // The precedence of paths is as listed above, i.e. we take the first path
2731 // that exists. Note that we never include libc++ twice -- we take the first
2732 // path that exists and don't send the other paths to CC1 (otherwise
2733 // include_next could break).
2734
2735 // Check for (1)
2736 // Get from '<install>/bin' to '<install>/include/c++/v1'.
2737 // Note that InstallBin can be relative, so we use '..' instead of
2738 // parent_path.
2739 llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin
2740 llvm::sys::path::append(path&: InstallBin, a: "..", b: "include", c: "c++", d: "v1");
2741 if (getVFS().exists(Path: InstallBin)) {
2742 addSystemInclude(DriverArgs, CC1Args, Path: InstallBin);
2743 return;
2744 } else if (DriverArgs.hasArg(options::OPT_v)) {
2745 llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
2746 << "\"\n";
2747 }
2748
2749 // Otherwise, check for (2)
2750 llvm::SmallString<128> SysrootUsr = Sysroot;
2751 llvm::sys::path::append(path&: SysrootUsr, a: "usr", b: "include", c: "c++", d: "v1");
2752 if (getVFS().exists(Path: SysrootUsr)) {
2753 addSystemInclude(DriverArgs, CC1Args, Path: SysrootUsr);
2754 return;
2755 } else if (DriverArgs.hasArg(options::OPT_v)) {
2756 llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
2757 << "\"\n";
2758 }
2759
2760 // Otherwise, don't add any path.
2761 break;
2762 }
2763
2764 case ToolChain::CST_Libstdcxx:
2765 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args);
2766 break;
2767 }
2768}
2769
2770void AppleMachO::AddGnuCPlusPlusIncludePaths(
2771 const llvm::opt::ArgList &DriverArgs,
2772 llvm::opt::ArgStringList &CC1Args) const {}
2773
2774void DarwinClang::AddGnuCPlusPlusIncludePaths(
2775 const llvm::opt::ArgList &DriverArgs,
2776 llvm::opt::ArgStringList &CC1Args) const {
2777 llvm::SmallString<128> UsrIncludeCxx = GetEffectiveSysroot(DriverArgs);
2778 llvm::sys::path::append(path&: UsrIncludeCxx, a: "usr", b: "include", c: "c++");
2779
2780 llvm::Triple::ArchType arch = getTriple().getArch();
2781 bool IsBaseFound = true;
2782 switch (arch) {
2783 default:
2784 break;
2785
2786 case llvm::Triple::x86:
2787 case llvm::Triple::x86_64:
2788 IsBaseFound = AddGnuCPlusPlusIncludePaths(
2789 DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1", ArchDir: "i686-apple-darwin10",
2790 BitDir: arch == llvm::Triple::x86_64 ? "x86_64" : "");
2791 IsBaseFound |= AddGnuCPlusPlusIncludePaths(
2792 DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.0.0", ArchDir: "i686-apple-darwin8", BitDir: "");
2793 break;
2794
2795 case llvm::Triple::arm:
2796 case llvm::Triple::thumb:
2797 IsBaseFound =
2798 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1",
2799 ArchDir: "arm-apple-darwin10", BitDir: "v7");
2800 IsBaseFound |=
2801 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1",
2802 ArchDir: "arm-apple-darwin10", BitDir: "v6");
2803 break;
2804
2805 case llvm::Triple::aarch64:
2806 IsBaseFound =
2807 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, Base: UsrIncludeCxx, Version: "4.2.1",
2808 ArchDir: "arm64-apple-darwin10", BitDir: "");
2809 break;
2810 }
2811
2812 if (!IsBaseFound) {
2813 getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2814 }
2815}
2816
2817void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args,
2818 ArgStringList &CmdArgs) const {
2819 CXXStdlibType Type = GetCXXStdlibType(Args);
2820
2821 switch (Type) {
2822 case ToolChain::CST_Libcxx:
2823 CmdArgs.push_back(Elt: "-lc++");
2824 if (Args.hasArg(options::OPT_fexperimental_library))
2825 CmdArgs.push_back(Elt: "-lc++experimental");
2826 break;
2827
2828 case ToolChain::CST_Libstdcxx:
2829 // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
2830 // it was previously found in the gcc lib dir. However, for all the Darwin
2831 // platforms we care about it was -lstdc++.6, so we search for that
2832 // explicitly if we can't see an obvious -lstdc++ candidate.
2833
2834 // Check in the sysroot first.
2835 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2836 SmallString<128> P(A->getValue());
2837 llvm::sys::path::append(path&: P, a: "usr", b: "lib", c: "libstdc++.dylib");
2838
2839 if (!getVFS().exists(Path: P)) {
2840 llvm::sys::path::remove_filename(path&: P);
2841 llvm::sys::path::append(path&: P, a: "libstdc++.6.dylib");
2842 if (getVFS().exists(Path: P)) {
2843 CmdArgs.push_back(Elt: Args.MakeArgString(Str: P));
2844 return;
2845 }
2846 }
2847 }
2848
2849 // Otherwise, look in the root.
2850 // FIXME: This should be removed someday when we don't have to care about
2851 // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
2852 if (!getVFS().exists(Path: "/usr/lib/libstdc++.dylib") &&
2853 getVFS().exists(Path: "/usr/lib/libstdc++.6.dylib")) {
2854 CmdArgs.push_back(Elt: "/usr/lib/libstdc++.6.dylib");
2855 return;
2856 }
2857
2858 // Otherwise, let the linker search.
2859 CmdArgs.push_back(Elt: "-lstdc++");
2860 break;
2861 }
2862}
2863
2864void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
2865 ArgStringList &CmdArgs) const {
2866 // For Darwin platforms, use the compiler-rt-based support library
2867 // instead of the gcc-provided one (which is also incidentally
2868 // only present in the gcc lib dir, which makes it hard to find).
2869
2870 SmallString<128> P(getDriver().ResourceDir);
2871 llvm::sys::path::append(path&: P, a: "lib", b: "darwin");
2872
2873 // Use the newer cc_kext for iOS ARM after 6.0.
2874 if (isTargetWatchOS()) {
2875 llvm::sys::path::append(path&: P, a: "libclang_rt.cc_kext_watchos.a");
2876 } else if (isTargetTvOS()) {
2877 llvm::sys::path::append(path&: P, a: "libclang_rt.cc_kext_tvos.a");
2878 } else if (isTargetIPhoneOS()) {
2879 llvm::sys::path::append(path&: P, a: "libclang_rt.cc_kext_ios.a");
2880 } else if (isTargetDriverKit()) {
2881 // DriverKit doesn't want extra runtime support.
2882 } else if (isTargetXROSDevice()) {
2883 llvm::sys::path::append(
2884 path&: P, a: llvm::Twine("libclang_rt.cc_kext_") +
2885 llvm::Triple::getOSTypeName(Kind: llvm::Triple::XROS) + ".a");
2886 } else {
2887 llvm::sys::path::append(path&: P, a: "libclang_rt.cc_kext.a");
2888 }
2889
2890 // For now, allow missing resource libraries to support developers who may
2891 // not have compiler-rt checked out or integrated into their build.
2892 if (getVFS().exists(Path: P))
2893 CmdArgs.push_back(Elt: Args.MakeArgString(Str: P));
2894}
2895
2896DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
2897 StringRef BoundArch,
2898 Action::OffloadKind) const {
2899 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
2900 const OptTable &Opts = getDriver().getOpts();
2901
2902 // FIXME: We really want to get out of the tool chain level argument
2903 // translation business, as it makes the driver functionality much
2904 // more opaque. For now, we follow gcc closely solely for the
2905 // purpose of easily achieving feature parity & testability. Once we
2906 // have something that works, we should reevaluate each translation
2907 // and try to push it down into tool specific logic.
2908
2909 for (Arg *A : Args) {
2910 // Sob. These is strictly gcc compatible for the time being. Apple
2911 // gcc translates options twice, which means that self-expanding
2912 // options add duplicates.
2913 switch ((options::ID)A->getOption().getID()) {
2914 default:
2915 DAL->append(A);
2916 break;
2917
2918 case options::OPT_mkernel:
2919 case options::OPT_fapple_kext:
2920 DAL->append(A);
2921 DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
2922 break;
2923
2924 case options::OPT_dependency_file:
2925 DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
2926 break;
2927
2928 case options::OPT_gfull:
2929 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2930 DAL->AddFlagArg(
2931 A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
2932 break;
2933
2934 case options::OPT_gused:
2935 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2936 DAL->AddFlagArg(
2937 A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
2938 break;
2939
2940 case options::OPT_shared:
2941 DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
2942 break;
2943
2944 case options::OPT_fconstant_cfstrings:
2945 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
2946 break;
2947
2948 case options::OPT_fno_constant_cfstrings:
2949 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
2950 break;
2951
2952 case options::OPT_Wnonportable_cfstrings:
2953 DAL->AddFlagArg(A,
2954 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
2955 break;
2956
2957 case options::OPT_Wno_nonportable_cfstrings:
2958 DAL->AddFlagArg(
2959 A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
2960 break;
2961 }
2962 }
2963
2964 // Add the arch options based on the particular spelling of -arch, to match
2965 // how the driver works.
2966 if (!BoundArch.empty()) {
2967 StringRef Name = BoundArch;
2968 const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
2969 const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);
2970
2971 // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
2972 // which defines the list of which architectures we accept.
2973 if (Name == "ppc")
2974 ;
2975 else if (Name == "ppc601")
2976 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "601");
2977 else if (Name == "ppc603")
2978 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "603");
2979 else if (Name == "ppc604")
2980 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "604");
2981 else if (Name == "ppc604e")
2982 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "604e");
2983 else if (Name == "ppc750")
2984 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "750");
2985 else if (Name == "ppc7400")
2986 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "7400");
2987 else if (Name == "ppc7450")
2988 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "7450");
2989 else if (Name == "ppc970")
2990 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MCpu, Value: "970");
2991
2992 else if (Name == "ppc64" || Name == "ppc64le")
2993 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2994
2995 else if (Name == "i386")
2996 ;
2997 else if (Name == "i486")
2998 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "i486");
2999 else if (Name == "i586")
3000 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "i586");
3001 else if (Name == "i686")
3002 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "i686");
3003 else if (Name == "pentium")
3004 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentium");
3005 else if (Name == "pentium2")
3006 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentium2");
3007 else if (Name == "pentpro")
3008 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentiumpro");
3009 else if (Name == "pentIIm3")
3010 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "pentium2");
3011
3012 else if (Name == "x86_64" || Name == "x86_64h")
3013 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
3014
3015 else if (Name == "arm")
3016 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv4t");
3017 else if (Name == "armv4t")
3018 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv4t");
3019 else if (Name == "armv5")
3020 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv5tej");
3021 else if (Name == "xscale")
3022 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "xscale");
3023 else if (Name == "armv6")
3024 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv6k");
3025 else if (Name == "armv6m")
3026 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv6m");
3027 else if (Name == "armv7")
3028 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7a");
3029 else if (Name == "armv7em")
3030 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7em");
3031 else if (Name == "armv7k")
3032 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7k");
3033 else if (Name == "armv7m")
3034 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7m");
3035 else if (Name == "armv7s")
3036 DAL->AddJoinedArg(BaseArg: nullptr, Opt: MArch, Value: "armv7s");
3037 }
3038
3039 return DAL;
3040}
3041
3042void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
3043 ArgStringList &CmdArgs,
3044 bool ForceLinkBuiltinRT) const {
3045 // Embedded targets are simple at the moment, not supporting sanitizers and
3046 // with different libraries for each member of the product { static, PIC } x
3047 // { hard-float, soft-float }
3048 llvm::SmallString<32> CompilerRT = StringRef("");
3049 CompilerRT +=
3050 (tools::arm::getARMFloatABI(TC: *this, Args) == tools::arm::FloatABI::Hard)
3051 ? "hard"
3052 : "soft";
3053 CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
3054
3055 AddLinkRuntimeLib(Args, CmdArgs, Component: CompilerRT, Opts: RLO_IsEmbedded);
3056}
3057
3058bool Darwin::isAlignedAllocationUnavailable() const {
3059 llvm::Triple::OSType OS;
3060
3061 if (isTargetMacCatalyst())
3062 return TargetVersion < alignedAllocMinVersion(OS: llvm::Triple::MacOSX);
3063 switch (TargetPlatform) {
3064 case MacOS: // Earlier than 10.13.
3065 OS = llvm::Triple::MacOSX;
3066 break;
3067 case IPhoneOS:
3068 OS = llvm::Triple::IOS;
3069 break;
3070 case TvOS: // Earlier than 11.0.
3071 OS = llvm::Triple::TvOS;
3072 break;
3073 case WatchOS: // Earlier than 4.0.
3074 OS = llvm::Triple::WatchOS;
3075 break;
3076 case XROS: // Always available.
3077 return false;
3078 case DriverKit: // Always available.
3079 return false;
3080 }
3081
3082 return TargetVersion < alignedAllocMinVersion(OS);
3083}
3084
3085static bool
3086sdkSupportsBuiltinModules(const std::optional<DarwinSDKInfo> &SDKInfo) {
3087 if (!SDKInfo)
3088 // If there is no SDK info, assume this is building against a
3089 // pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those
3090 // don't support modules anyway, but the headers definitely
3091 // don't support builtin modules either. It might also be some
3092 // kind of degenerate build environment, err on the side of
3093 // the old behavior which is to not use builtin modules.
3094 return false;
3095
3096 VersionTuple SDKVersion = SDKInfo->getVersion();
3097 switch (SDKInfo->getOS()) {
3098 // Existing SDKs added support for builtin modules in the fall
3099 // 2024 major releases.
3100 case llvm::Triple::MacOSX:
3101 return SDKVersion >= VersionTuple(15U);
3102 case llvm::Triple::IOS:
3103 return SDKVersion >= VersionTuple(18U);
3104 case llvm::Triple::TvOS:
3105 return SDKVersion >= VersionTuple(18U);
3106 case llvm::Triple::WatchOS:
3107 return SDKVersion >= VersionTuple(11U);
3108 case llvm::Triple::XROS:
3109 return SDKVersion >= VersionTuple(2U);
3110
3111 // New SDKs support builtin modules from the start.
3112 default:
3113 return true;
3114 }
3115}
3116
3117static inline llvm::VersionTuple
3118sizedDeallocMinVersion(llvm::Triple::OSType OS) {
3119 switch (OS) {
3120 default:
3121 break;
3122 case llvm::Triple::Darwin:
3123 case llvm::Triple::MacOSX: // Earliest supporting version is 10.12.
3124 return llvm::VersionTuple(10U, 12U);
3125 case llvm::Triple::IOS:
3126 case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0.
3127 return llvm::VersionTuple(10U);
3128 case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0.
3129 return llvm::VersionTuple(3U);
3130 }
3131
3132 llvm_unreachable("Unexpected OS");
3133}
3134
3135bool Darwin::isSizedDeallocationUnavailable() const {
3136 llvm::Triple::OSType OS;
3137
3138 if (isTargetMacCatalyst())
3139 return TargetVersion < sizedDeallocMinVersion(OS: llvm::Triple::MacOSX);
3140 switch (TargetPlatform) {
3141 case MacOS: // Earlier than 10.12.
3142 OS = llvm::Triple::MacOSX;
3143 break;
3144 case IPhoneOS:
3145 OS = llvm::Triple::IOS;
3146 break;
3147 case TvOS: // Earlier than 10.0.
3148 OS = llvm::Triple::TvOS;
3149 break;
3150 case WatchOS: // Earlier than 3.0.
3151 OS = llvm::Triple::WatchOS;
3152 break;
3153 case DriverKit:
3154 case XROS:
3155 // Always available.
3156 return false;
3157 }
3158
3159 return TargetVersion < sizedDeallocMinVersion(OS);
3160}
3161
3162void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
3163 llvm::opt::ArgStringList &CC1Args,
3164 Action::OffloadKind DeviceOffloadKind) const {
3165
3166 ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
3167
3168 // On arm64e, enable pointer authentication (for the return address and
3169 // indirect calls), as well as usage of the intrinsics.
3170 if (getArchName() == "arm64e") {
3171 if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,
3172 options::OPT_fno_ptrauth_returns))
3173 CC1Args.push_back(Elt: "-fptrauth-returns");
3174
3175 if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,
3176 options::OPT_fno_ptrauth_intrinsics))
3177 CC1Args.push_back(Elt: "-fptrauth-intrinsics");
3178
3179 if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,
3180 options::OPT_fno_ptrauth_calls))
3181 CC1Args.push_back(Elt: "-fptrauth-calls");
3182
3183 if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
3184 options::OPT_fno_ptrauth_indirect_gotos))
3185 CC1Args.push_back(Elt: "-fptrauth-indirect-gotos");
3186
3187 if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,
3188 options::OPT_fno_ptrauth_auth_traps))
3189 CC1Args.push_back(Elt: "-fptrauth-auth-traps");
3190 }
3191}
3192
3193void Darwin::addClangTargetOptions(
3194 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
3195 Action::OffloadKind DeviceOffloadKind) const {
3196
3197 MachO::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);
3198
3199 // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
3200 // enabled or disabled aligned allocations.
3201 if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
3202 options::OPT_fno_aligned_allocation) &&
3203 isAlignedAllocationUnavailable())
3204 CC1Args.push_back(Elt: "-faligned-alloc-unavailable");
3205
3206 // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled
3207 // or disabled sized deallocations.
3208 if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,
3209 options::OPT_fno_sized_deallocation) &&
3210 isSizedDeallocationUnavailable())
3211 CC1Args.push_back(Elt: "-fno-sized-deallocation");
3212
3213 addClangCC1ASTargetOptions(Args: DriverArgs, CC1ASArgs&: CC1Args);
3214
3215 // Enable compatibility mode for NSItemProviderCompletionHandler in
3216 // Foundation/NSItemProvider.h.
3217 CC1Args.push_back(Elt: "-fcompatibility-qualified-id-block-type-checking");
3218
3219 // Give static local variables in inline functions hidden visibility when
3220 // -fvisibility-inlines-hidden is enabled.
3221 if (!DriverArgs.getLastArgNoClaim(
3222 options::OPT_fvisibility_inlines_hidden_static_local_var,
3223 options::OPT_fno_visibility_inlines_hidden_static_local_var))
3224 CC1Args.push_back(Elt: "-fvisibility-inlines-hidden-static-local-var");
3225
3226 // Earlier versions of the darwin SDK have the C standard library headers
3227 // all together in the Darwin module. That leads to module cycles with
3228 // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
3229 // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
3230 // darwin headers are in the Darwin module, there's a module cycle Darwin ->
3231 // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
3232 // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
3233 // but until then, the builtin headers need to join the system modules.
3234 // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
3235 // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
3236 // to fix the same problem with C++ headers, and is generally fragile.
3237 if (!sdkSupportsBuiltinModules(SDKInfo))
3238 CC1Args.push_back(Elt: "-fbuiltin-headers-in-system-modules");
3239
3240 if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,
3241 options::OPT_fno_define_target_os_macros))
3242 CC1Args.push_back(Elt: "-fdefine-target-os-macros");
3243
3244 // Disable subdirectory modulemap search on sufficiently recent SDKs.
3245 if (SDKInfo &&
3246 !DriverArgs.hasFlag(options::OPT_fmodulemap_allow_subdirectory_search,
3247 options::OPT_fno_modulemap_allow_subdirectory_search,
3248 false)) {
3249 bool RequiresSubdirectorySearch;
3250 VersionTuple SDKVersion = SDKInfo->getVersion();
3251 switch (TargetPlatform) {
3252 default:
3253 RequiresSubdirectorySearch = true;
3254 break;
3255 case MacOS:
3256 RequiresSubdirectorySearch = SDKVersion < VersionTuple(15, 0);
3257 break;
3258 case IPhoneOS:
3259 case TvOS:
3260 RequiresSubdirectorySearch = SDKVersion < VersionTuple(18, 0);
3261 break;
3262 case WatchOS:
3263 RequiresSubdirectorySearch = SDKVersion < VersionTuple(11, 0);
3264 break;
3265 case XROS:
3266 RequiresSubdirectorySearch = SDKVersion < VersionTuple(2, 0);
3267 break;
3268 }
3269 if (!RequiresSubdirectorySearch)
3270 CC1Args.push_back(Elt: "-fno-modulemap-allow-subdirectory-search");
3271 }
3272}
3273
3274void Darwin::addClangCC1ASTargetOptions(
3275 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
3276 if (TargetVariantTriple) {
3277 CC1ASArgs.push_back(Elt: "-darwin-target-variant-triple");
3278 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: TargetVariantTriple->getTriple()));
3279 }
3280
3281 if (SDKInfo) {
3282 /// Pass the SDK version to the compiler when the SDK information is
3283 /// available.
3284 auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
3285 std::string Arg;
3286 llvm::raw_string_ostream OS(Arg);
3287 OS << "-target-sdk-version=" << V;
3288 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: Arg));
3289 };
3290
3291 if (isTargetMacCatalyst()) {
3292 if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
3293 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3294 std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
3295 Key: SDKInfo->getVersion(), MinimumValue: minimumMacCatalystDeploymentTarget(),
3296 MaximumValue: std::nullopt);
3297 EmitTargetSDKVersionArg(
3298 SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
3299 }
3300 } else {
3301 EmitTargetSDKVersionArg(SDKInfo->getVersion());
3302 }
3303
3304 /// Pass the target variant SDK version to the compiler when the SDK
3305 /// information is available and is required for target variant.
3306 if (TargetVariantTriple) {
3307 if (isTargetMacCatalyst()) {
3308 std::string Arg;
3309 llvm::raw_string_ostream OS(Arg);
3310 OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
3311 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: Arg));
3312 } else if (const auto *MacOStoMacCatalystMapping =
3313 SDKInfo->getVersionMapping(
3314 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3315 if (std::optional<VersionTuple> SDKVersion =
3316 MacOStoMacCatalystMapping->map(
3317 Key: SDKInfo->getVersion(), MinimumValue: minimumMacCatalystDeploymentTarget(),
3318 MaximumValue: std::nullopt)) {
3319 std::string Arg;
3320 llvm::raw_string_ostream OS(Arg);
3321 OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
3322 CC1ASArgs.push_back(Elt: Args.MakeArgString(Str: Arg));
3323 }
3324 }
3325 }
3326 }
3327}
3328
3329DerivedArgList *
3330Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
3331 Action::OffloadKind DeviceOffloadKind) const {
3332 // First get the generic Apple args, before moving onto Darwin-specific ones.
3333 DerivedArgList *DAL =
3334 MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
3335
3336 // If no architecture is bound, none of the translations here are relevant.
3337 if (BoundArch.empty())
3338 return DAL;
3339
3340 // Add an explicit version min argument for the deployment target. We do this
3341 // after argument translation because -Xarch_ arguments may add a version min
3342 // argument.
3343 AddDeploymentTarget(Args&: *DAL);
3344
3345 // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
3346 // FIXME: It would be far better to avoid inserting those -static arguments,
3347 // but we can't check the deployment target in the translation code until
3348 // it is set here.
3349 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||
3350 (isTargetIOSBased() && !isIPhoneOSVersionLT(V0: 6, V1: 0))) {
3351 for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
3352 Arg *A = *it;
3353 ++it;
3354 if (A->getOption().getID() != options::OPT_mkernel &&
3355 A->getOption().getID() != options::OPT_fapple_kext)
3356 continue;
3357 assert(it != ie && "unexpected argument translation");
3358 A = *it;
3359 assert(A->getOption().getID() == options::OPT_static &&
3360 "missing expected -static argument");
3361 *it = nullptr;
3362 ++it;
3363 }
3364 }
3365
3366 auto Arch = tools::darwin::getArchTypeForMachOArchName(Str: BoundArch);
3367 if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
3368 if (Args.hasFlag(options::OPT_fomit_frame_pointer,
3369 options::OPT_fno_omit_frame_pointer, false))
3370 getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
3371 << "-fomit-frame-pointer" << BoundArch;
3372 }
3373
3374 return DAL;
3375}
3376
3377ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
3378 // Unwind tables are not emitted if -fno-exceptions is supplied (except when
3379 // targeting x86_64).
3380 if (getArch() == llvm::Triple::x86_64 ||
3381 (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
3382 Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
3383 true)))
3384 return (getArch() == llvm::Triple::aarch64 ||
3385 getArch() == llvm::Triple::aarch64_32)
3386 ? UnwindTableLevel::Synchronous
3387 : UnwindTableLevel::Asynchronous;
3388
3389 return UnwindTableLevel::None;
3390}
3391
3392bool MachO::UseDwarfDebugFlags() const {
3393 if (const char *S = ::getenv(name: "RC_DEBUG_OPTIONS"))
3394 return S[0] != '\0';
3395 return false;
3396}
3397
3398std::string MachO::GetGlobalDebugPathRemapping() const {
3399 if (const char *S = ::getenv(name: "RC_DEBUG_PREFIX_MAP"))
3400 return S;
3401 return {};
3402}
3403
3404llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
3405 // Darwin uses SjLj exceptions on ARM.
3406 if (getTriple().getArch() != llvm::Triple::arm &&
3407 getTriple().getArch() != llvm::Triple::thumb)
3408 return llvm::ExceptionHandling::None;
3409
3410 // Only watchOS uses the new DWARF/Compact unwinding method.
3411 llvm::Triple Triple(ComputeLLVMTriple(Args));
3412 if (Triple.isWatchABI())
3413 return llvm::ExceptionHandling::DwarfCFI;
3414
3415 return llvm::ExceptionHandling::SjLj;
3416}
3417
3418bool Darwin::SupportsEmbeddedBitcode() const {
3419 assert(TargetInitialized && "Target not initialized!");
3420 if (isTargetIPhoneOS() && isIPhoneOSVersionLT(V0: 6, V1: 0))
3421 return false;
3422 return true;
3423}
3424
3425bool MachO::isPICDefault() const { return true; }
3426
3427bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
3428
3429bool MachO::isPICDefaultForced() const {
3430 return (getArch() == llvm::Triple::x86_64 ||
3431 getArch() == llvm::Triple::aarch64);
3432}
3433
3434bool MachO::SupportsProfiling() const {
3435 // Profiling instrumentation is only supported on x86.
3436 return getTriple().isX86();
3437}
3438
3439void Darwin::addMinVersionArgs(const ArgList &Args,
3440 ArgStringList &CmdArgs) const {
3441 VersionTuple TargetVersion = getTripleTargetVersion();
3442
3443 assert(!isTargetXROS() && "xrOS always uses -platform-version");
3444
3445 if (isTargetWatchOS())
3446 CmdArgs.push_back(Elt: "-watchos_version_min");
3447 else if (isTargetWatchOSSimulator())
3448 CmdArgs.push_back(Elt: "-watchos_simulator_version_min");
3449 else if (isTargetTvOS())
3450 CmdArgs.push_back(Elt: "-tvos_version_min");
3451 else if (isTargetTvOSSimulator())
3452 CmdArgs.push_back(Elt: "-tvos_simulator_version_min");
3453 else if (isTargetDriverKit())
3454 CmdArgs.push_back(Elt: "-driverkit_version_min");
3455 else if (isTargetIOSSimulator())
3456 CmdArgs.push_back(Elt: "-ios_simulator_version_min");
3457 else if (isTargetIOSBased())
3458 CmdArgs.push_back(Elt: "-iphoneos_version_min");
3459 else if (isTargetMacCatalyst())
3460 CmdArgs.push_back(Elt: "-maccatalyst_version_min");
3461 else {
3462 assert(isTargetMacOS() && "unexpected target");
3463 CmdArgs.push_back(Elt: "-macosx_version_min");
3464 }
3465
3466 VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
3467 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3468 TargetVersion = MinTgtVers;
3469 CmdArgs.push_back(Elt: Args.MakeArgString(Str: TargetVersion.getAsString()));
3470 if (TargetVariantTriple) {
3471 assert(isTargetMacOSBased() && "unexpected target");
3472 VersionTuple VariantTargetVersion;
3473 if (TargetVariantTriple->isMacOSX()) {
3474 CmdArgs.push_back(Elt: "-macosx_version_min");
3475 TargetVariantTriple->getMacOSXVersion(Version&: VariantTargetVersion);
3476 } else {
3477 assert(TargetVariantTriple->isiOS() &&
3478 TargetVariantTriple->isMacCatalystEnvironment() &&
3479 "unexpected target variant triple");
3480 CmdArgs.push_back(Elt: "-maccatalyst_version_min");
3481 VariantTargetVersion = TargetVariantTriple->getiOSVersion();
3482 }
3483 VersionTuple MinTgtVers =
3484 TargetVariantTriple->getMinimumSupportedOSVersion();
3485 if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
3486 VariantTargetVersion = MinTgtVers;
3487 CmdArgs.push_back(Elt: Args.MakeArgString(Str: VariantTargetVersion.getAsString()));
3488 }
3489}
3490
3491static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
3492 Darwin::DarwinEnvironmentKind Environment) {
3493 switch (Platform) {
3494 case Darwin::MacOS:
3495 return "macos";
3496 case Darwin::IPhoneOS:
3497 if (Environment == Darwin::MacCatalyst)
3498 return "mac catalyst";
3499 return "ios";
3500 case Darwin::TvOS:
3501 return "tvos";
3502 case Darwin::WatchOS:
3503 return "watchos";
3504 case Darwin::XROS:
3505 return "xros";
3506 case Darwin::DriverKit:
3507 return "driverkit";
3508 }
3509 llvm_unreachable("invalid platform");
3510}
3511
3512void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
3513 llvm::opt::ArgStringList &CmdArgs) const {
3514 auto EmitPlatformVersionArg =
3515 [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
3516 Darwin::DarwinEnvironmentKind TargetEnvironment,
3517 const llvm::Triple &TT) {
3518 // -platform_version <platform> <target_version> <sdk_version>
3519 // Both the target and SDK version support only up to 3 components.
3520 CmdArgs.push_back(Elt: "-platform_version");
3521 std::string PlatformName =
3522 getPlatformName(Platform: TargetPlatform, Environment: TargetEnvironment);
3523 if (TargetEnvironment == Darwin::Simulator)
3524 PlatformName += "-simulator";
3525 CmdArgs.push_back(Elt: Args.MakeArgString(Str: PlatformName));
3526 VersionTuple TargetVersion = TV.withoutBuild();
3527 if ((TargetPlatform == Darwin::IPhoneOS ||
3528 TargetPlatform == Darwin::TvOS) &&
3529 getTriple().getArchName() == "arm64e" &&
3530 TargetVersion.getMajor() < 14) {
3531 // arm64e slice is supported on iOS/tvOS 14+ only.
3532 TargetVersion = VersionTuple(14, 0);
3533 }
3534 VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
3535 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3536 TargetVersion = MinTgtVers;
3537 CmdArgs.push_back(Elt: Args.MakeArgString(Str: TargetVersion.getAsString()));
3538
3539 if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
3540 // Mac Catalyst programs must use the appropriate iOS SDK version
3541 // that corresponds to the macOS SDK version used for the compilation.
3542 std::optional<VersionTuple> iOSSDKVersion;
3543 if (SDKInfo) {
3544 if (const auto *MacOStoMacCatalystMapping =
3545 SDKInfo->getVersionMapping(
3546 Kind: DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3547 iOSSDKVersion = MacOStoMacCatalystMapping->map(
3548 Key: SDKInfo->getVersion().withoutBuild(),
3549 MinimumValue: minimumMacCatalystDeploymentTarget(), MaximumValue: std::nullopt);
3550 }
3551 }
3552 CmdArgs.push_back(Elt: Args.MakeArgString(
3553 Str: (iOSSDKVersion ? *iOSSDKVersion
3554 : minimumMacCatalystDeploymentTarget())
3555 .getAsString()));
3556 return;
3557 }
3558
3559 if (SDKInfo) {
3560 VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
3561 if (!SDKVersion.getMinor())
3562 SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
3563 CmdArgs.push_back(Elt: Args.MakeArgString(Str: SDKVersion.getAsString()));
3564 } else {
3565 // Use an SDK version that's matching the deployment target if the SDK
3566 // version is missing. This is preferred over an empty SDK version
3567 // (0.0.0) as the system's runtime might expect the linked binary to
3568 // contain a valid SDK version in order for the binary to work
3569 // correctly. It's reasonable to use the deployment target version as
3570 // a proxy for the SDK version because older SDKs don't guarantee
3571 // support for deployment targets newer than the SDK versions, so that
3572 // rules out using some predetermined older SDK version, which leaves
3573 // the deployment target version as the only reasonable choice.
3574 CmdArgs.push_back(Elt: Args.MakeArgString(Str: TargetVersion.getAsString()));
3575 }
3576 };
3577 EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
3578 TargetEnvironment, getEffectiveTriple());
3579 if (!TargetVariantTriple)
3580 return;
3581 Darwin::DarwinPlatformKind Platform;
3582 Darwin::DarwinEnvironmentKind Environment;
3583 VersionTuple TargetVariantVersion;
3584 if (TargetVariantTriple->isMacOSX()) {
3585 TargetVariantTriple->getMacOSXVersion(Version&: TargetVariantVersion);
3586 Platform = Darwin::MacOS;
3587 Environment = Darwin::NativeEnvironment;
3588 } else {
3589 assert(TargetVariantTriple->isiOS() &&
3590 TargetVariantTriple->isMacCatalystEnvironment() &&
3591 "unexpected target variant triple");
3592 TargetVariantVersion = TargetVariantTriple->getiOSVersion();
3593 Platform = Darwin::IPhoneOS;
3594 Environment = Darwin::MacCatalyst;
3595 }
3596 EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
3597 *TargetVariantTriple);
3598}
3599
3600// Add additional link args for the -dynamiclib option.
3601static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
3602 ArgStringList &CmdArgs) {
3603 // Derived from darwin_dylib1 spec.
3604 if (D.isTargetIPhoneOS()) {
3605 if (D.isIPhoneOSVersionLT(V0: 3, V1: 1))
3606 CmdArgs.push_back(Elt: "-ldylib1.o");
3607 return;
3608 }
3609
3610 if (!D.isTargetMacOS())
3611 return;
3612 if (D.isMacosxVersionLT(V0: 10, V1: 5))
3613 CmdArgs.push_back(Elt: "-ldylib1.o");
3614 else if (D.isMacosxVersionLT(V0: 10, V1: 6))
3615 CmdArgs.push_back(Elt: "-ldylib1.10.5.o");
3616}
3617
3618// Add additional link args for the -bundle option.
3619static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
3620 ArgStringList &CmdArgs) {
3621 if (Args.hasArg(options::OPT_static))
3622 return;
3623 // Derived from darwin_bundle1 spec.
3624 if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(V0: 3, V1: 1)) ||
3625 (D.isTargetMacOS() && D.isMacosxVersionLT(V0: 10, V1: 6)))
3626 CmdArgs.push_back(Elt: "-lbundle1.o");
3627}
3628
3629// Add additional link args for the -pg option.
3630static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
3631 ArgStringList &CmdArgs) {
3632 if (D.isTargetMacOS() && D.isMacosxVersionLT(V0: 10, V1: 9)) {
3633 if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
3634 Args.hasArg(options::OPT_preload)) {
3635 CmdArgs.push_back(Elt: "-lgcrt0.o");
3636 } else {
3637 CmdArgs.push_back(Elt: "-lgcrt1.o");
3638
3639 // darwin_crt2 spec is empty.
3640 }
3641 // By default on OS X 10.8 and later, we don't link with a crt1.o
3642 // file and the linker knows to use _main as the entry point. But,
3643 // when compiling with -pg, we need to link with the gcrt1.o file,
3644 // so pass the -no_new_main option to tell the linker to use the
3645 // "start" symbol as the entry point.
3646 if (!D.isMacosxVersionLT(V0: 10, V1: 8))
3647 CmdArgs.push_back(Elt: "-no_new_main");
3648 } else {
3649 D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
3650 << D.isTargetMacOSBased();
3651 }
3652}
3653
3654static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
3655 ArgStringList &CmdArgs) {
3656 // Derived from darwin_crt1 spec.
3657 if (D.isTargetIPhoneOS()) {
3658 if (D.getArch() == llvm::Triple::aarch64)
3659 ; // iOS does not need any crt1 files for arm64
3660 else if (D.isIPhoneOSVersionLT(V0: 3, V1: 1))
3661 CmdArgs.push_back(Elt: "-lcrt1.o");
3662 else if (D.isIPhoneOSVersionLT(V0: 6, V1: 0))
3663 CmdArgs.push_back(Elt: "-lcrt1.3.1.o");
3664 return;
3665 }
3666
3667 if (!D.isTargetMacOS())
3668 return;
3669 if (D.isMacosxVersionLT(V0: 10, V1: 5))
3670 CmdArgs.push_back(Elt: "-lcrt1.o");
3671 else if (D.isMacosxVersionLT(V0: 10, V1: 6))
3672 CmdArgs.push_back(Elt: "-lcrt1.10.5.o");
3673 else if (D.isMacosxVersionLT(V0: 10, V1: 8))
3674 CmdArgs.push_back(Elt: "-lcrt1.10.6.o");
3675 // darwin_crt2 spec is empty.
3676}
3677
3678void Darwin::addStartObjectFileArgs(const ArgList &Args,
3679 ArgStringList &CmdArgs) const {
3680 // Derived from startfile spec.
3681 if (Args.hasArg(options::OPT_dynamiclib))
3682 addDynamicLibLinkArgs(D: *this, Args, CmdArgs);
3683 else if (Args.hasArg(options::OPT_bundle))
3684 addBundleLinkArgs(D: *this, Args, CmdArgs);
3685 else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
3686 addPgProfilingLinkArgs(D: *this, Args, CmdArgs);
3687 else if (Args.hasArg(options::OPT_static) ||
3688 Args.hasArg(options::OPT_object) ||
3689 Args.hasArg(options::OPT_preload))
3690 CmdArgs.push_back(Elt: "-lcrt0.o");
3691 else
3692 addDefaultCRTLinkArgs(D: *this, Args, CmdArgs);
3693
3694 if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
3695 isMacosxVersionLT(10, 5)) {
3696 const char *Str = Args.MakeArgString(Str: GetFilePath(Name: "crt3.o"));
3697 CmdArgs.push_back(Elt: Str);
3698 }
3699}
3700
3701void Darwin::CheckObjCARC() const {
3702 if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||
3703 (isTargetMacOSBased() && !isMacosxVersionLT(V0: 10, V1: 6)))
3704 return;
3705 getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
3706}
3707
3708SanitizerMask Darwin::getSupportedSanitizers() const {
3709 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
3710 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
3711 SanitizerMask Res = ToolChain::getSupportedSanitizers();
3712 Res |= SanitizerKind::Address;
3713 Res |= SanitizerKind::PointerCompare;
3714 Res |= SanitizerKind::PointerSubtract;
3715 Res |= SanitizerKind::Realtime;
3716 Res |= SanitizerKind::Leak;
3717 Res |= SanitizerKind::Fuzzer;
3718 Res |= SanitizerKind::FuzzerNoLink;
3719 Res |= SanitizerKind::ObjCCast;
3720
3721 // Prior to 10.9, macOS shipped a version of the C++ standard library without
3722 // C++11 support. The same is true of iOS prior to version 5. These OS'es are
3723 // incompatible with -fsanitize=vptr.
3724 if (!(isTargetMacOSBased() && isMacosxVersionLT(V0: 10, V1: 9)) &&
3725 !(isTargetIPhoneOS() && isIPhoneOSVersionLT(V0: 5, V1: 0)))
3726 Res |= SanitizerKind::Vptr;
3727
3728 if ((IsX86_64 || IsAArch64) &&
3729 (isTargetMacOSBased() || isTargetIOSSimulator() ||
3730 isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
3731 Res |= SanitizerKind::Thread;
3732 }
3733
3734 if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {
3735 Res |= SanitizerKind::Type;
3736 }
3737
3738 if (IsX86_64)
3739 Res |= SanitizerKind::NumericalStability;
3740
3741 return Res;
3742}
3743
3744void AppleMachO::printVerboseInfo(raw_ostream &OS) const {
3745 CudaInstallation->print(OS);
3746 RocmInstallation->print(OS);
3747}
3748

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Driver/ToolChains/Darwin.cpp