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