[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Driver / ToolChains / Darwin.cpp
blobf28e08d81bf29b48c69236265c6d3928fe89b044
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/Threading.h"
27 #include "llvm/Support/VirtualFileSystem.h"
28 #include "llvm/TargetParser/TargetParser.h"
29 #include "llvm/TargetParser/Triple.h"
30 #include <cstdlib> // ::getenv
32 using namespace clang::driver;
33 using namespace clang::driver::tools;
34 using namespace clang::driver::toolchains;
35 using namespace clang;
36 using namespace llvm::opt;
38 static VersionTuple minimumMacCatalystDeploymentTarget() {
39 return VersionTuple(13, 1);
42 llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
43 // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
44 // archs which Darwin doesn't use.
46 // The matching this routine does is fairly pointless, since it is neither the
47 // complete architecture list, nor a reasonable subset. The problem is that
48 // historically the driver accepts this and also ties its -march=
49 // handling to the architecture name, so we need to be careful before removing
50 // support for it.
52 // This code must be kept in sync with Clang's Darwin specific argument
53 // translation.
55 return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
56 .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
57 .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
58 llvm::Triple::x86)
59 .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
60 // This is derived from the driver.
61 .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
62 .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
63 .Cases("armv7s", "xscale", llvm::Triple::arm)
64 .Cases("arm64", "arm64e", llvm::Triple::aarch64)
65 .Case("arm64_32", llvm::Triple::aarch64_32)
66 .Case("r600", llvm::Triple::r600)
67 .Case("amdgcn", llvm::Triple::amdgcn)
68 .Case("nvptx", llvm::Triple::nvptx)
69 .Case("nvptx64", llvm::Triple::nvptx64)
70 .Case("amdil", llvm::Triple::amdil)
71 .Case("spir", llvm::Triple::spir)
72 .Default(llvm::Triple::UnknownArch);
75 void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,
76 const ArgList &Args) {
77 const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
78 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
79 T.setArch(Arch);
80 if (Arch != llvm::Triple::UnknownArch)
81 T.setArchName(Str);
83 if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
84 ArchKind == llvm::ARM::ArchKind::ARMV7M ||
85 ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
86 // Don't reject these -version-min= if we have the appropriate triple.
87 if (T.getOS() == llvm::Triple::IOS)
88 for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ))
89 A->ignoreTargetSpecific();
90 if (T.getOS() == llvm::Triple::WatchOS)
91 for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))
92 A->ignoreTargetSpecific();
93 if (T.getOS() == llvm::Triple::TvOS)
94 for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))
95 A->ignoreTargetSpecific();
97 T.setOS(llvm::Triple::UnknownOS);
98 T.setObjectFormat(llvm::Triple::MachO);
102 void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
103 const InputInfo &Output,
104 const InputInfoList &Inputs,
105 const ArgList &Args,
106 const char *LinkingOutput) const {
107 const llvm::Triple &T(getToolChain().getTriple());
109 ArgStringList CmdArgs;
111 assert(Inputs.size() == 1 && "Unexpected number of inputs.");
112 const InputInfo &Input = Inputs[0];
114 // Determine the original source input.
115 const Action *SourceAction = &JA;
116 while (SourceAction->getKind() != Action::InputClass) {
117 assert(!SourceAction->getInputs().empty() && "unexpected root action!");
118 SourceAction = SourceAction->getInputs()[0];
121 // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
122 // sure it runs its system assembler not clang's integrated assembler.
123 // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
124 // FIXME: at run-time detect assembler capabilities or rely on version
125 // information forwarded by -target-assembler-version.
126 if (Args.hasArg(options::OPT_fno_integrated_as)) {
127 if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
128 CmdArgs.push_back("-Q");
131 // Forward -g, assuming we are dealing with an actual assembly file.
132 if (SourceAction->getType() == types::TY_Asm ||
133 SourceAction->getType() == types::TY_PP_Asm) {
134 if (Args.hasArg(options::OPT_gstabs))
135 CmdArgs.push_back("--gstabs");
136 else if (Args.hasArg(options::OPT_g_Group))
137 CmdArgs.push_back("-g");
140 // Derived from asm spec.
141 AddMachOArch(Args, CmdArgs);
143 // Use -force_cpusubtype_ALL on x86 by default.
144 if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))
145 CmdArgs.push_back("-force_cpusubtype_ALL");
147 if (getToolChain().getArch() != llvm::Triple::x86_64 &&
148 (((Args.hasArg(options::OPT_mkernel) ||
149 Args.hasArg(options::OPT_fapple_kext)) &&
150 getMachOToolChain().isKernelStatic()) ||
151 Args.hasArg(options::OPT_static)))
152 CmdArgs.push_back("-static");
154 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
156 assert(Output.isFilename() && "Unexpected lipo output.");
157 CmdArgs.push_back("-o");
158 CmdArgs.push_back(Output.getFilename());
160 assert(Input.isFilename() && "Invalid input.");
161 CmdArgs.push_back(Input.getFilename());
163 // asm_final spec is empty.
165 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
166 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
167 Exec, CmdArgs, Inputs, Output));
170 void darwin::MachOTool::anchor() {}
172 void darwin::MachOTool::AddMachOArch(const ArgList &Args,
173 ArgStringList &CmdArgs) const {
174 StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
176 // Derived from darwin_arch spec.
177 CmdArgs.push_back("-arch");
178 CmdArgs.push_back(Args.MakeArgString(ArchName));
180 // FIXME: Is this needed anymore?
181 if (ArchName == "arm")
182 CmdArgs.push_back("-force_cpusubtype_ALL");
185 bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
186 // We only need to generate a temp path for LTO if we aren't compiling object
187 // files. When compiling source files, we run 'dsymutil' after linking. We
188 // don't run 'dsymutil' when compiling object files.
189 for (const auto &Input : Inputs)
190 if (Input.getType() != types::TY_Object)
191 return true;
193 return false;
196 /// Pass -no_deduplicate to ld64 under certain conditions:
198 /// - Either -O0 or -O1 is explicitly specified
199 /// - No -O option is specified *and* this is a compile+link (implicit -O0)
201 /// Also do *not* add -no_deduplicate when no -O option is specified and this
202 /// is just a link (we can't imply -O0)
203 static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
204 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
205 if (A->getOption().matches(options::OPT_O0))
206 return true;
207 if (A->getOption().matches(options::OPT_O))
208 return llvm::StringSwitch<bool>(A->getValue())
209 .Case("1", true)
210 .Default(false);
211 return false; // OPT_Ofast & OPT_O4
214 if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
215 return true;
216 return false;
219 void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
220 ArgStringList &CmdArgs,
221 const InputInfoList &Inputs,
222 VersionTuple Version, bool LinkerIsLLD) const {
223 const Driver &D = getToolChain().getDriver();
224 const toolchains::MachO &MachOTC = getMachOToolChain();
226 // Newer linkers support -demangle. Pass it if supported and not disabled by
227 // the user.
228 if ((Version >= VersionTuple(100) || LinkerIsLLD) &&
229 !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
230 CmdArgs.push_back("-demangle");
232 if (Args.hasArg(options::OPT_rdynamic) &&
233 (Version >= VersionTuple(137) || LinkerIsLLD))
234 CmdArgs.push_back("-export_dynamic");
236 // If we are using App Extension restrictions, pass a flag to the linker
237 // telling it that the compiled code has been audited.
238 if (Args.hasFlag(options::OPT_fapplication_extension,
239 options::OPT_fno_application_extension, false))
240 CmdArgs.push_back("-application_extension");
242 if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&
243 NeedsTempPath(Inputs)) {
244 std::string TmpPathName;
245 if (D.getLTOMode() == LTOK_Full) {
246 // If we are using full LTO, then automatically create a temporary file
247 // path for the linker to use, so that it's lifetime will extend past a
248 // possible dsymutil step.
249 TmpPathName =
250 D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
251 } else if (D.getLTOMode() == LTOK_Thin)
252 // If we are using thin LTO, then create a directory instead.
253 TmpPathName = D.GetTemporaryDirectory("thinlto");
255 if (!TmpPathName.empty()) {
256 auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
257 C.addTempFile(TmpPath);
258 CmdArgs.push_back("-object_path_lto");
259 CmdArgs.push_back(TmpPath);
263 // Use -lto_library option to specify the libLTO.dylib path. Try to find
264 // it in clang installed libraries. ld64 will only look at this argument
265 // when it actually uses LTO, so libLTO.dylib only needs to exist at link
266 // time if ld64 decides that it needs to use LTO.
267 // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
268 // next to it. That's ok since ld64 using a libLTO.dylib not matching the
269 // clang version won't work anyways.
270 // lld is built at the same revision as clang and statically links in
271 // LLVM libraries, so it doesn't need libLTO.dylib.
272 if (Version >= VersionTuple(133) && !LinkerIsLLD) {
273 // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
274 StringRef P = llvm::sys::path::parent_path(D.Dir);
275 SmallString<128> LibLTOPath(P);
276 llvm::sys::path::append(LibLTOPath, "lib");
277 llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
278 CmdArgs.push_back("-lto_library");
279 CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
282 // ld64 version 262 and above runs the deduplicate pass by default.
283 // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`
284 // if `!shouldLinkerNotDedup()` if LinkerIsLLD here?
285 if (Version >= VersionTuple(262) &&
286 shouldLinkerNotDedup(C.getJobs().empty(), Args))
287 CmdArgs.push_back("-no_deduplicate");
289 // Derived from the "link" spec.
290 Args.AddAllArgs(CmdArgs, options::OPT_static);
291 if (!Args.hasArg(options::OPT_static))
292 CmdArgs.push_back("-dynamic");
293 if (Args.hasArg(options::OPT_fgnu_runtime)) {
294 // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
295 // here. How do we wish to handle such things?
298 if (!Args.hasArg(options::OPT_dynamiclib)) {
299 AddMachOArch(Args, CmdArgs);
300 // FIXME: Why do this only on this path?
301 Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
303 Args.AddLastArg(CmdArgs, options::OPT_bundle);
304 Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
305 Args.AddAllArgs(CmdArgs, options::OPT_client__name);
307 Arg *A;
308 if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
309 (A = Args.getLastArg(options::OPT_current__version)) ||
310 (A = Args.getLastArg(options::OPT_install__name)))
311 D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
312 << "-dynamiclib";
314 Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
315 Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
316 Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
317 } else {
318 CmdArgs.push_back("-dylib");
320 Arg *A;
321 if ((A = Args.getLastArg(options::OPT_bundle)) ||
322 (A = Args.getLastArg(options::OPT_bundle__loader)) ||
323 (A = Args.getLastArg(options::OPT_client__name)) ||
324 (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
325 (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
326 (A = Args.getLastArg(options::OPT_private__bundle)))
327 D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
328 << "-dynamiclib";
330 Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
331 "-dylib_compatibility_version");
332 Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
333 "-dylib_current_version");
335 AddMachOArch(Args, CmdArgs);
337 Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
338 "-dylib_install_name");
341 Args.AddLastArg(CmdArgs, options::OPT_all__load);
342 Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
343 Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
344 if (MachOTC.isTargetIOSBased())
345 Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
346 Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
347 Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
348 Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
349 Args.AddLastArg(CmdArgs, options::OPT_dynamic);
350 Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
351 Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
352 Args.AddAllArgs(CmdArgs, options::OPT_force__load);
353 Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
354 Args.AddAllArgs(CmdArgs, options::OPT_image__base);
355 Args.AddAllArgs(CmdArgs, options::OPT_init);
357 // Add the deployment target.
358 if (Version >= VersionTuple(520) || LinkerIsLLD)
359 MachOTC.addPlatformVersionArgs(Args, CmdArgs);
360 else
361 MachOTC.addMinVersionArgs(Args, CmdArgs);
363 Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
364 Args.AddLastArg(CmdArgs, options::OPT_multi__module);
365 Args.AddLastArg(CmdArgs, options::OPT_single__module);
366 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
367 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
369 if (const Arg *A =
370 Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
371 options::OPT_fno_pie, options::OPT_fno_PIE)) {
372 if (A->getOption().matches(options::OPT_fpie) ||
373 A->getOption().matches(options::OPT_fPIE))
374 CmdArgs.push_back("-pie");
375 else
376 CmdArgs.push_back("-no_pie");
379 // for embed-bitcode, use -bitcode_bundle in linker command
380 if (C.getDriver().embedBitcodeEnabled()) {
381 // Check if the toolchain supports bitcode build flow.
382 if (MachOTC.SupportsEmbeddedBitcode()) {
383 CmdArgs.push_back("-bitcode_bundle");
384 // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.
385 if (C.getDriver().embedBitcodeMarkerOnly() &&
386 Version >= VersionTuple(278)) {
387 CmdArgs.push_back("-bitcode_process_mode");
388 CmdArgs.push_back("marker");
390 } else
391 D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
394 // If GlobalISel is enabled, pass it through to LLVM.
395 if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
396 options::OPT_fno_global_isel)) {
397 if (A->getOption().matches(options::OPT_fglobal_isel)) {
398 CmdArgs.push_back("-mllvm");
399 CmdArgs.push_back("-global-isel");
400 // Disable abort and fall back to SDAG silently.
401 CmdArgs.push_back("-mllvm");
402 CmdArgs.push_back("-global-isel-abort=0");
406 if (Args.hasArg(options::OPT_mkernel) ||
407 Args.hasArg(options::OPT_fapple_kext) ||
408 Args.hasArg(options::OPT_ffreestanding)) {
409 CmdArgs.push_back("-mllvm");
410 CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");
413 Args.AddLastArg(CmdArgs, options::OPT_prebind);
414 Args.AddLastArg(CmdArgs, options::OPT_noprebind);
415 Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
416 Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
417 Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
418 Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
419 Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
420 Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
421 Args.AddAllArgs(CmdArgs, options::OPT_segprot);
422 Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
423 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
424 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
425 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
426 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
427 Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
428 Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
430 // Give --sysroot= preference, over the Apple specific behavior to also use
431 // --isysroot as the syslibroot.
432 StringRef sysroot = C.getSysRoot();
433 if (sysroot != "") {
434 CmdArgs.push_back("-syslibroot");
435 CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
436 } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
437 CmdArgs.push_back("-syslibroot");
438 CmdArgs.push_back(A->getValue());
441 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
442 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
443 Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
444 Args.AddAllArgs(CmdArgs, options::OPT_undefined);
445 Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
446 Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
447 Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
448 Args.AddAllArgs(CmdArgs, options::OPT_y);
449 Args.AddLastArg(CmdArgs, options::OPT_w);
450 Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
451 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
452 Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
453 Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
454 Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
455 Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
456 Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
457 Args.AddLastArg(CmdArgs, options::OPT_why_load);
458 Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
459 Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
460 Args.AddLastArg(CmdArgs, options::OPT_dylinker);
461 Args.AddLastArg(CmdArgs, options::OPT_Mach);
463 if (LinkerIsLLD) {
464 if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
465 SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0
466 ? ""
467 : CSPGOGenerateArg->getValue());
468 llvm::sys::path::append(Path, "default_%m.profraw");
469 CmdArgs.push_back("--cs-profile-generate");
470 CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
471 } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
472 SmallString<128> Path(
473 ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
474 if (Path.empty() || llvm::sys::fs::is_directory(Path))
475 llvm::sys::path::append(Path, "default.profdata");
476 CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
481 /// Determine whether we are linking the ObjC runtime.
482 static bool isObjCRuntimeLinked(const ArgList &Args) {
483 if (isObjCAutoRefCount(Args)) {
484 Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
485 return true;
487 return Args.hasArg(options::OPT_fobjc_link_runtime);
490 static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
491 const llvm::Triple &Triple) {
492 // When enabling remarks, we need to error if:
493 // * The remark file is specified but we're targeting multiple architectures,
494 // which means more than one remark file is being generated.
495 bool hasMultipleInvocations =
496 Args.getAllArgValues(options::OPT_arch).size() > 1;
497 bool hasExplicitOutputFile =
498 Args.getLastArg(options::OPT_foptimization_record_file_EQ);
499 if (hasMultipleInvocations && hasExplicitOutputFile) {
500 D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
501 << "-foptimization-record-file";
502 return false;
504 return true;
507 static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
508 const llvm::Triple &Triple,
509 const InputInfo &Output, const JobAction &JA) {
510 StringRef Format = "yaml";
511 if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
512 Format = A->getValue();
514 CmdArgs.push_back("-mllvm");
515 CmdArgs.push_back("-lto-pass-remarks-output");
516 CmdArgs.push_back("-mllvm");
518 const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
519 if (A) {
520 CmdArgs.push_back(A->getValue());
521 } else {
522 assert(Output.isFilename() && "Unexpected ld output.");
523 SmallString<128> F;
524 F = Output.getFilename();
525 F += ".opt.";
526 F += Format;
528 CmdArgs.push_back(Args.MakeArgString(F));
531 if (const Arg *A =
532 Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
533 CmdArgs.push_back("-mllvm");
534 std::string Passes =
535 std::string("-lto-pass-remarks-filter=") + A->getValue();
536 CmdArgs.push_back(Args.MakeArgString(Passes));
539 if (!Format.empty()) {
540 CmdArgs.push_back("-mllvm");
541 Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
542 CmdArgs.push_back(Args.MakeArgString(FormatArg));
545 if (getLastProfileUseArg(Args)) {
546 CmdArgs.push_back("-mllvm");
547 CmdArgs.push_back("-lto-pass-remarks-with-hotness");
549 if (const Arg *A =
550 Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
551 CmdArgs.push_back("-mllvm");
552 std::string Opt =
553 std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
554 CmdArgs.push_back(Args.MakeArgString(Opt));
559 static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);
561 void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
562 const InputInfo &Output,
563 const InputInfoList &Inputs,
564 const ArgList &Args,
565 const char *LinkingOutput) const {
566 assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
568 // If the number of arguments surpasses the system limits, we will encode the
569 // input files in a separate file, shortening the command line. To this end,
570 // build a list of input file names that can be passed via a file with the
571 // -filelist linker option.
572 llvm::opt::ArgStringList InputFileList;
574 // The logic here is derived from gcc's behavior; most of which
575 // comes from specs (starting with link_command). Consult gcc for
576 // more information.
577 ArgStringList CmdArgs;
579 /// Hack(tm) to ignore linking errors when we are doing ARC migration.
580 if (Args.hasArg(options::OPT_ccc_arcmt_check,
581 options::OPT_ccc_arcmt_migrate)) {
582 for (const auto &Arg : Args)
583 Arg->claim();
584 const char *Exec =
585 Args.MakeArgString(getToolChain().GetProgramPath("touch"));
586 CmdArgs.push_back(Output.getFilename());
587 C.addCommand(std::make_unique<Command>(JA, *this,
588 ResponseFileSupport::None(), Exec,
589 CmdArgs, std::nullopt, Output));
590 return;
593 VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
595 bool LinkerIsLLD;
596 const char *Exec =
597 Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));
599 // I'm not sure why this particular decomposition exists in gcc, but
600 // we follow suite for ease of comparison.
601 AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD);
603 if (willEmitRemarks(Args) &&
604 checkRemarksOptions(getToolChain().getDriver(), Args,
605 getToolChain().getTriple()))
606 renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);
608 // Propagate the -moutline flag to the linker in LTO.
609 if (Arg *A =
610 Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {
611 if (A->getOption().matches(options::OPT_moutline)) {
612 if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
613 CmdArgs.push_back("-mllvm");
614 CmdArgs.push_back("-enable-machine-outliner");
616 } else {
617 // Disable all outlining behaviour if we have mno-outline. We need to do
618 // this explicitly, because targets which support default outlining will
619 // try to do work if we don't.
620 CmdArgs.push_back("-mllvm");
621 CmdArgs.push_back("-enable-machine-outliner=never");
625 // Outline from linkonceodr functions by default in LTO, whenever the outliner
626 // is enabled. Note that the target may enable the machine outliner
627 // independently of -moutline.
628 CmdArgs.push_back("-mllvm");
629 CmdArgs.push_back("-enable-linkonceodr-outlining");
631 // Setup statistics file output.
632 SmallString<128> StatsFile =
633 getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
634 if (!StatsFile.empty()) {
635 CmdArgs.push_back("-mllvm");
636 CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));
639 // It seems that the 'e' option is completely ignored for dynamic executables
640 // (the default), and with static executables, the last one wins, as expected.
641 Args.addAllArgs(CmdArgs,
642 {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
643 options::OPT_Z_Flag, options::OPT_u_Group, options::OPT_r});
645 // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
646 // members of static archive libraries which implement Objective-C classes or
647 // categories.
648 if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
649 CmdArgs.push_back("-ObjC");
651 CmdArgs.push_back("-o");
652 CmdArgs.push_back(Output.getFilename());
654 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
655 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
657 Args.AddAllArgs(CmdArgs, options::OPT_L);
659 AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
660 // Build the input file for -filelist (list of linker input files) in case we
661 // need it later
662 for (const auto &II : Inputs) {
663 if (!II.isFilename()) {
664 // This is a linker input argument.
665 // We cannot mix input arguments and file names in a -filelist input, thus
666 // we prematurely stop our list (remaining files shall be passed as
667 // arguments).
668 if (InputFileList.size() > 0)
669 break;
671 continue;
674 InputFileList.push_back(II.getFilename());
677 // Additional linker set-up and flags for Fortran. This is required in order
678 // to generate executables.
679 if (getToolChain().getDriver().IsFlangMode()) {
680 addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
681 addFortranRuntimeLibs(getToolChain(), CmdArgs);
684 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
685 addOpenMPRuntime(CmdArgs, getToolChain(), Args);
687 if (isObjCRuntimeLinked(Args) &&
688 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
689 // We use arclite library for both ARC and subscripting support.
690 getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
692 CmdArgs.push_back("-framework");
693 CmdArgs.push_back("Foundation");
694 // Link libobj.
695 CmdArgs.push_back("-lobjc");
698 if (LinkingOutput) {
699 CmdArgs.push_back("-arch_multiple");
700 CmdArgs.push_back("-final_output");
701 CmdArgs.push_back(LinkingOutput);
704 if (Args.hasArg(options::OPT_fnested_functions))
705 CmdArgs.push_back("-allow_stack_execute");
707 getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
709 StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
710 if (!Parallelism.empty()) {
711 CmdArgs.push_back("-mllvm");
712 unsigned NumThreads =
713 llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
714 CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
717 if (getToolChain().ShouldLinkCXXStdlib(Args))
718 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
720 bool NoStdOrDefaultLibs =
721 Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
722 bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
723 if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
724 // link_ssp spec is empty.
726 // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
727 // we just want to link the builtins, not the other libs like libSystem.
728 if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
729 getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");
730 } else {
731 // Let the tool chain choose which runtime library to link.
732 getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
733 ForceLinkBuiltins);
735 // No need to do anything for pthreads. Claim argument to avoid warning.
736 Args.ClaimAllArgs(options::OPT_pthread);
737 Args.ClaimAllArgs(options::OPT_pthreads);
741 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
742 // endfile_spec is empty.
745 Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
746 Args.AddAllArgs(CmdArgs, options::OPT_F);
748 // -iframework should be forwarded as -F.
749 for (const Arg *A : Args.filtered(options::OPT_iframework))
750 CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
752 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
753 if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
754 if (A->getValue() == StringRef("Accelerate")) {
755 CmdArgs.push_back("-framework");
756 CmdArgs.push_back("Accelerate");
761 // Add non-standard, platform-specific search paths, e.g., for DriverKit:
762 // -L<sysroot>/System/DriverKit/usr/lib
763 // -F<sysroot>/System/DriverKit/System/Library/Framework
765 bool NonStandardSearchPath = false;
766 const auto &Triple = getToolChain().getTriple();
767 if (Triple.isDriverKit()) {
768 // ld64 fixed the implicit -F and -L paths in ld64-605.1+.
769 NonStandardSearchPath =
770 Version.getMajor() < 605 ||
771 (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);
774 if (NonStandardSearchPath) {
775 if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
776 auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
777 SmallString<128> P(Sysroot->getValue());
778 AppendPlatformPrefix(P, Triple);
779 llvm::sys::path::append(P, SearchPath);
780 if (getToolChain().getVFS().exists(P)) {
781 CmdArgs.push_back(Args.MakeArgString(Flag + P));
784 AddSearchPath("-L", "/usr/lib");
785 AddSearchPath("-F", "/System/Library/Frameworks");
790 ResponseFileSupport ResponseSupport;
791 if (Version >= VersionTuple(705) || LinkerIsLLD) {
792 ResponseSupport = ResponseFileSupport::AtFileUTF8();
793 } else {
794 // For older versions of the linker, use the legacy filelist method instead.
795 ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
796 "-filelist"};
799 std::unique_ptr<Command> Cmd = std::make_unique<Command>(
800 JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
801 Cmd->setInputFileList(std::move(InputFileList));
802 C.addCommand(std::move(Cmd));
805 void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
806 const InputInfo &Output,
807 const InputInfoList &Inputs,
808 const ArgList &Args,
809 const char *LinkingOutput) const {
810 const Driver &D = getToolChain().getDriver();
812 // Silence warning for "clang -g foo.o -o foo"
813 Args.ClaimAllArgs(options::OPT_g_Group);
814 // and "clang -emit-llvm foo.o -o foo"
815 Args.ClaimAllArgs(options::OPT_emit_llvm);
816 // and for "clang -w foo.o -o foo". Other warning options are already
817 // handled somewhere else.
818 Args.ClaimAllArgs(options::OPT_w);
819 // Silence warnings when linking C code with a C++ '-stdlib' argument.
820 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
822 // libtool <options> <output_file> <input_files>
823 ArgStringList CmdArgs;
824 // Create and insert file members with a deterministic index.
825 CmdArgs.push_back("-static");
826 CmdArgs.push_back("-D");
827 CmdArgs.push_back("-no_warning_for_no_symbols");
828 CmdArgs.push_back("-o");
829 CmdArgs.push_back(Output.getFilename());
831 for (const auto &II : Inputs) {
832 if (II.isFilename()) {
833 CmdArgs.push_back(II.getFilename());
837 // Delete old output archive file if it already exists before generating a new
838 // archive file.
839 const auto *OutputFileName = Output.getFilename();
840 if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
841 if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
842 D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
843 return;
847 const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
848 C.addCommand(std::make_unique<Command>(JA, *this,
849 ResponseFileSupport::AtFileUTF8(),
850 Exec, CmdArgs, Inputs, Output));
853 void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
854 const InputInfo &Output,
855 const InputInfoList &Inputs,
856 const ArgList &Args,
857 const char *LinkingOutput) const {
858 ArgStringList CmdArgs;
860 CmdArgs.push_back("-create");
861 assert(Output.isFilename() && "Unexpected lipo output.");
863 CmdArgs.push_back("-output");
864 CmdArgs.push_back(Output.getFilename());
866 for (const auto &II : Inputs) {
867 assert(II.isFilename() && "Unexpected lipo input.");
868 CmdArgs.push_back(II.getFilename());
871 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
872 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
873 Exec, CmdArgs, Inputs, Output));
876 void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
877 const InputInfo &Output,
878 const InputInfoList &Inputs,
879 const ArgList &Args,
880 const char *LinkingOutput) const {
881 ArgStringList CmdArgs;
883 CmdArgs.push_back("-o");
884 CmdArgs.push_back(Output.getFilename());
886 assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
887 const InputInfo &Input = Inputs[0];
888 assert(Input.isFilename() && "Unexpected dsymutil input.");
889 CmdArgs.push_back(Input.getFilename());
891 const char *Exec =
892 Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
893 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
894 Exec, CmdArgs, Inputs, Output));
897 void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
898 const InputInfo &Output,
899 const InputInfoList &Inputs,
900 const ArgList &Args,
901 const char *LinkingOutput) const {
902 ArgStringList CmdArgs;
903 CmdArgs.push_back("--verify");
904 CmdArgs.push_back("--debug-info");
905 CmdArgs.push_back("--eh-frame");
906 CmdArgs.push_back("--quiet");
908 assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
909 const InputInfo &Input = Inputs[0];
910 assert(Input.isFilename() && "Unexpected verify input");
912 // Grabbing the output of the earlier dsymutil run.
913 CmdArgs.push_back(Input.getFilename());
915 const char *Exec =
916 Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
917 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
918 Exec, CmdArgs, Inputs, Output));
921 MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
922 : ToolChain(D, Triple, Args) {
923 // We expect 'as', 'ld', etc. to be adjacent to our install dir.
924 getProgramPaths().push_back(getDriver().getInstalledDir());
925 if (getDriver().getInstalledDir() != getDriver().Dir)
926 getProgramPaths().push_back(getDriver().Dir);
929 /// Darwin - Darwin tool chain for i386 and x86_64.
930 Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
931 : MachO(D, Triple, Args), TargetInitialized(false),
932 CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
934 types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
935 types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
937 // Darwin always preprocesses assembly files (unless -x is used explicitly).
938 if (Ty == types::TY_PP_Asm)
939 return types::TY_Asm;
941 return Ty;
944 bool MachO::HasNativeLLVMSupport() const { return true; }
946 ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
947 // Always use libc++ by default
948 return ToolChain::CST_Libcxx;
951 /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
952 ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
953 if (isTargetWatchOSBased())
954 return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
955 if (isTargetIOSBased())
956 return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
957 if (isNonFragile)
958 return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
959 return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
962 /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
963 bool Darwin::hasBlocksRuntime() const {
964 if (isTargetWatchOSBased() || isTargetDriverKit())
965 return true;
966 else if (isTargetIOSBased())
967 return !isIPhoneOSVersionLT(3, 2);
968 else {
969 assert(isTargetMacOSBased() && "unexpected darwin target");
970 return !isMacosxVersionLT(10, 6);
974 void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
975 ArgStringList &CC1Args) const {
976 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
979 void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
980 ArgStringList &CC1Args) const {
981 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
984 // This is just a MachO name translation routine and there's no
985 // way to join this into ARMTargetParser without breaking all
986 // other assumptions. Maybe MachO should consider standardising
987 // their nomenclature.
988 static const char *ArmMachOArchName(StringRef Arch) {
989 return llvm::StringSwitch<const char *>(Arch)
990 .Case("armv6k", "armv6")
991 .Case("armv6m", "armv6m")
992 .Case("armv5tej", "armv5")
993 .Case("xscale", "xscale")
994 .Case("armv4t", "armv4t")
995 .Case("armv7", "armv7")
996 .Cases("armv7a", "armv7-a", "armv7")
997 .Cases("armv7r", "armv7-r", "armv7")
998 .Cases("armv7em", "armv7e-m", "armv7em")
999 .Cases("armv7k", "armv7-k", "armv7k")
1000 .Cases("armv7m", "armv7-m", "armv7m")
1001 .Cases("armv7s", "armv7-s", "armv7s")
1002 .Default(nullptr);
1005 static const char *ArmMachOArchNameCPU(StringRef CPU) {
1006 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
1007 if (ArchKind == llvm::ARM::ArchKind::INVALID)
1008 return nullptr;
1009 StringRef Arch = llvm::ARM::getArchName(ArchKind);
1011 // FIXME: Make sure this MachO triple mangling is really necessary.
1012 // ARMv5* normalises to ARMv5.
1013 if (Arch.startswith("armv5"))
1014 Arch = Arch.substr(0, 5);
1015 // ARMv6*, except ARMv6M, normalises to ARMv6.
1016 else if (Arch.startswith("armv6") && !Arch.endswith("6m"))
1017 Arch = Arch.substr(0, 5);
1018 // ARMv7A normalises to ARMv7.
1019 else if (Arch.endswith("v7a"))
1020 Arch = Arch.substr(0, 5);
1021 return Arch.data();
1024 StringRef MachO::getMachOArchName(const ArgList &Args) const {
1025 switch (getTriple().getArch()) {
1026 default:
1027 return getDefaultUniversalArchName();
1029 case llvm::Triple::aarch64_32:
1030 return "arm64_32";
1032 case llvm::Triple::aarch64: {
1033 if (getTriple().isArm64e())
1034 return "arm64e";
1035 return "arm64";
1038 case llvm::Triple::thumb:
1039 case llvm::Triple::arm:
1040 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
1041 if (const char *Arch = ArmMachOArchName(A->getValue()))
1042 return Arch;
1044 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
1045 if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
1046 return Arch;
1048 return "arm";
1052 VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
1053 if (LinkerVersion) {
1054 #ifndef NDEBUG
1055 VersionTuple NewLinkerVersion;
1056 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1057 (void)NewLinkerVersion.tryParse(A->getValue());
1058 assert(NewLinkerVersion == LinkerVersion);
1059 #endif
1060 return *LinkerVersion;
1063 VersionTuple NewLinkerVersion;
1064 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1065 if (NewLinkerVersion.tryParse(A->getValue()))
1066 getDriver().Diag(diag::err_drv_invalid_version_number)
1067 << A->getAsString(Args);
1069 LinkerVersion = NewLinkerVersion;
1070 return *LinkerVersion;
1073 Darwin::~Darwin() {}
1075 MachO::~MachO() {}
1077 std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
1078 types::ID InputType) const {
1079 llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
1081 // If the target isn't initialized (e.g., an unknown Darwin platform, return
1082 // the default triple).
1083 if (!isTargetInitialized())
1084 return Triple.getTriple();
1086 SmallString<16> Str;
1087 if (isTargetWatchOSBased())
1088 Str += "watchos";
1089 else if (isTargetTvOSBased())
1090 Str += "tvos";
1091 else if (isTargetDriverKit())
1092 Str += "driverkit";
1093 else if (isTargetIOSBased() || isTargetMacCatalyst())
1094 Str += "ios";
1095 else
1096 Str += "macosx";
1097 Str += getTripleTargetVersion().getAsString();
1098 Triple.setOSName(Str);
1100 return Triple.getTriple();
1103 Tool *MachO::getTool(Action::ActionClass AC) const {
1104 switch (AC) {
1105 case Action::LipoJobClass:
1106 if (!Lipo)
1107 Lipo.reset(new tools::darwin::Lipo(*this));
1108 return Lipo.get();
1109 case Action::DsymutilJobClass:
1110 if (!Dsymutil)
1111 Dsymutil.reset(new tools::darwin::Dsymutil(*this));
1112 return Dsymutil.get();
1113 case Action::VerifyDebugInfoJobClass:
1114 if (!VerifyDebug)
1115 VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
1116 return VerifyDebug.get();
1117 default:
1118 return ToolChain::getTool(AC);
1122 Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
1124 Tool *MachO::buildStaticLibTool() const {
1125 return new tools::darwin::StaticLibTool(*this);
1128 Tool *MachO::buildAssembler() const {
1129 return new tools::darwin::Assembler(*this);
1132 DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
1133 const ArgList &Args)
1134 : Darwin(D, Triple, Args) {}
1136 void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
1137 // Always error about undefined 'TARGET_OS_*' macros.
1138 CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
1139 CC1Args.push_back("-Werror=undef-prefix");
1141 // For modern targets, promote certain warnings to errors.
1142 if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
1143 // Always enable -Wdeprecated-objc-isa-usage and promote it
1144 // to an error.
1145 CC1Args.push_back("-Wdeprecated-objc-isa-usage");
1146 CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
1148 // For iOS and watchOS, also error about implicit function declarations,
1149 // as that can impact calling conventions.
1150 if (!isTargetMacOS())
1151 CC1Args.push_back("-Werror=implicit-function-declaration");
1155 /// Take a path that speculatively points into Xcode and return the
1156 /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path
1157 /// otherwise.
1158 static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
1159 static constexpr llvm::StringLiteral XcodeAppSuffix(
1160 ".app/Contents/Developer");
1161 size_t Index = PathIntoXcode.find(XcodeAppSuffix);
1162 if (Index == StringRef::npos)
1163 return "";
1164 return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());
1167 void DarwinClang::AddLinkARCArgs(const ArgList &Args,
1168 ArgStringList &CmdArgs) const {
1169 // Avoid linking compatibility stubs on i386 mac.
1170 if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)
1171 return;
1172 if (isTargetAppleSiliconMac())
1173 return;
1174 // ARC runtime is supported everywhere on arm64e.
1175 if (getTriple().isArm64e())
1176 return;
1178 ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
1180 if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
1181 runtime.hasSubscripting())
1182 return;
1184 SmallString<128> P(getDriver().ClangExecutable);
1185 llvm::sys::path::remove_filename(P); // 'clang'
1186 llvm::sys::path::remove_filename(P); // 'bin'
1187 llvm::sys::path::append(P, "lib", "arc");
1189 // 'libarclite' usually lives in the same toolchain as 'clang'. However, the
1190 // Swift open source toolchains for macOS distribute Clang without libarclite.
1191 // In that case, to allow the linker to find 'libarclite', we point to the
1192 // 'libarclite' in the XcodeDefault toolchain instead.
1193 if (!getVFS().exists(P)) {
1194 auto updatePath = [&](const Arg *A) {
1195 // Try to infer the path to 'libarclite' in the toolchain from the
1196 // specified SDK path.
1197 StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
1198 if (XcodePathForSDK.empty())
1199 return false;
1201 P = XcodePathForSDK;
1202 llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
1203 "lib", "arc");
1204 return getVFS().exists(P);
1207 bool updated = false;
1208 if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
1209 updated = updatePath(A);
1211 if (!updated) {
1212 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
1213 updatePath(A);
1217 CmdArgs.push_back("-force_load");
1218 llvm::sys::path::append(P, "libarclite_");
1219 // Mash in the platform.
1220 if (isTargetWatchOSSimulator())
1221 P += "watchsimulator";
1222 else if (isTargetWatchOS())
1223 P += "watchos";
1224 else if (isTargetTvOSSimulator())
1225 P += "appletvsimulator";
1226 else if (isTargetTvOS())
1227 P += "appletvos";
1228 else if (isTargetIOSSimulator())
1229 P += "iphonesimulator";
1230 else if (isTargetIPhoneOS())
1231 P += "iphoneos";
1232 else
1233 P += "macosx";
1234 P += ".a";
1236 if (!getVFS().exists(P))
1237 getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;
1239 CmdArgs.push_back(Args.MakeArgString(P));
1242 unsigned DarwinClang::GetDefaultDwarfVersion() const {
1243 // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
1244 if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
1245 (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
1246 return 2;
1247 return 4;
1250 void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
1251 StringRef Component, RuntimeLinkOptions Opts,
1252 bool IsShared) const {
1253 SmallString<64> DarwinLibName = StringRef("libclang_rt.");
1254 // an Darwin the builtins compomnent is not in the library name
1255 if (Component != "builtins") {
1256 DarwinLibName += Component;
1257 if (!(Opts & RLO_IsEmbedded))
1258 DarwinLibName += "_";
1261 DarwinLibName += getOSLibraryNameSuffix();
1262 DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
1263 SmallString<128> Dir(getDriver().ResourceDir);
1264 llvm::sys::path::append(Dir, "lib", "darwin");
1265 if (Opts & RLO_IsEmbedded)
1266 llvm::sys::path::append(Dir, "macho_embedded");
1268 SmallString<128> P(Dir);
1269 llvm::sys::path::append(P, DarwinLibName);
1271 // For now, allow missing resource libraries to support developers who may
1272 // not have compiler-rt checked out or integrated into their build (unless
1273 // we explicitly force linking with this library).
1274 if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
1275 const char *LibArg = Args.MakeArgString(P);
1276 CmdArgs.push_back(LibArg);
1279 // Adding the rpaths might negatively interact when other rpaths are involved,
1280 // so we should make sure we add the rpaths last, after all user-specified
1281 // rpaths. This is currently true from this place, but we need to be
1282 // careful if this function is ever called before user's rpaths are emitted.
1283 if (Opts & RLO_AddRPath) {
1284 assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
1286 // Add @executable_path to rpath to support having the dylib copied with
1287 // the executable.
1288 CmdArgs.push_back("-rpath");
1289 CmdArgs.push_back("@executable_path");
1291 // Add the path to the resource dir to rpath to support using the dylib
1292 // from the default location without copying.
1293 CmdArgs.push_back("-rpath");
1294 CmdArgs.push_back(Args.MakeArgString(Dir));
1298 StringRef Darwin::getPlatformFamily() const {
1299 switch (TargetPlatform) {
1300 case DarwinPlatformKind::MacOS:
1301 return "MacOSX";
1302 case DarwinPlatformKind::IPhoneOS:
1303 if (TargetEnvironment == MacCatalyst)
1304 return "MacOSX";
1305 return "iPhone";
1306 case DarwinPlatformKind::TvOS:
1307 return "AppleTV";
1308 case DarwinPlatformKind::WatchOS:
1309 return "Watch";
1310 case DarwinPlatformKind::DriverKit:
1311 return "DriverKit";
1313 llvm_unreachable("Unsupported platform");
1316 StringRef Darwin::getSDKName(StringRef isysroot) {
1317 // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
1318 auto BeginSDK = llvm::sys::path::rbegin(isysroot);
1319 auto EndSDK = llvm::sys::path::rend(isysroot);
1320 for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
1321 StringRef SDK = *IT;
1322 if (SDK.endswith(".sdk"))
1323 return SDK.slice(0, SDK.size() - 4);
1325 return "";
1328 StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
1329 switch (TargetPlatform) {
1330 case DarwinPlatformKind::MacOS:
1331 return "osx";
1332 case DarwinPlatformKind::IPhoneOS:
1333 if (TargetEnvironment == MacCatalyst)
1334 return "osx";
1335 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
1336 : "iossim";
1337 case DarwinPlatformKind::TvOS:
1338 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
1339 : "tvossim";
1340 case DarwinPlatformKind::WatchOS:
1341 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
1342 : "watchossim";
1343 case DarwinPlatformKind::DriverKit:
1344 return "driverkit";
1346 llvm_unreachable("Unsupported platform");
1349 /// Check if the link command contains a symbol export directive.
1350 static bool hasExportSymbolDirective(const ArgList &Args) {
1351 for (Arg *A : Args) {
1352 if (A->getOption().matches(options::OPT_exported__symbols__list))
1353 return true;
1354 if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
1355 !A->getOption().matches(options::OPT_Xlinker))
1356 continue;
1357 if (A->containsValue("-exported_symbols_list") ||
1358 A->containsValue("-exported_symbol"))
1359 return true;
1361 return false;
1364 /// Add an export directive for \p Symbol to the link command.
1365 static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
1366 CmdArgs.push_back("-exported_symbol");
1367 CmdArgs.push_back(Symbol);
1370 /// Add a sectalign directive for \p Segment and \p Section to the maximum
1371 /// expected page size for Darwin.
1373 /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
1374 /// Use a common alignment constant (16K) for now, and reduce the alignment on
1375 /// macOS if it proves important.
1376 static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
1377 StringRef Segment, StringRef Section) {
1378 for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
1379 Args.MakeArgString(Section), "0x4000"})
1380 CmdArgs.push_back(A);
1383 void Darwin::addProfileRTLibs(const ArgList &Args,
1384 ArgStringList &CmdArgs) const {
1385 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1386 return;
1388 AddLinkRuntimeLib(Args, CmdArgs, "profile",
1389 RuntimeLinkOptions(RLO_AlwaysLink));
1391 bool ForGCOV = needsGCovInstrumentation(Args);
1393 // If we have a symbol export directive and we're linking in the profile
1394 // runtime, automatically export symbols necessary to implement some of the
1395 // runtime's functionality.
1396 if (hasExportSymbolDirective(Args) && ForGCOV) {
1397 addExportedSymbol(CmdArgs, "___gcov_dump");
1398 addExportedSymbol(CmdArgs, "___gcov_reset");
1399 addExportedSymbol(CmdArgs, "_writeout_fn_list");
1400 addExportedSymbol(CmdArgs, "_reset_fn_list");
1403 // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page
1404 // alignment. This allows profile counters to be mmap()'d to disk. Note that
1405 // it's not enough to just page-align __llvm_prf_cnts: the following section
1406 // must also be page-aligned so that its data is not clobbered by mmap().
1408 // The section alignment is only needed when continuous profile sync is
1409 // enabled, but this is expected to be the default in Xcode. Specifying the
1410 // extra alignment also allows the same binary to be used with/without sync
1411 // enabled.
1412 if (!ForGCOV) {
1413 for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {
1414 addSectalignToPage(
1415 Args, CmdArgs, "__DATA",
1416 llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
1417 /*AddSegmentInfo=*/false));
1422 void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
1423 ArgStringList &CmdArgs,
1424 StringRef Sanitizer,
1425 bool Shared) const {
1426 auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
1427 AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
1430 ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
1431 const ArgList &Args) const {
1432 if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
1433 StringRef Value = A->getValue();
1434 if (Value != "compiler-rt" && Value != "platform")
1435 getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
1436 << Value << "darwin";
1439 return ToolChain::RLT_CompilerRT;
1442 void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
1443 ArgStringList &CmdArgs,
1444 bool ForceLinkBuiltinRT) const {
1445 // Call once to ensure diagnostic is printed if wrong value was specified
1446 GetRuntimeLibType(Args);
1448 // Darwin doesn't support real static executables, don't link any runtime
1449 // libraries with -static.
1450 if (Args.hasArg(options::OPT_static) ||
1451 Args.hasArg(options::OPT_fapple_kext) ||
1452 Args.hasArg(options::OPT_mkernel)) {
1453 if (ForceLinkBuiltinRT)
1454 AddLinkRuntimeLib(Args, CmdArgs, "builtins");
1455 return;
1458 // Reject -static-libgcc for now, we can deal with this when and if someone
1459 // cares. This is useful in situations where someone wants to statically link
1460 // something like libstdc++, and needs its runtime support routines.
1461 if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
1462 getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
1463 return;
1466 const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
1468 if (!Sanitize.needsSharedRt()) {
1469 const char *sanitizer = nullptr;
1470 if (Sanitize.needsUbsanRt()) {
1471 sanitizer = "UndefinedBehaviorSanitizer";
1472 } else if (Sanitize.needsAsanRt()) {
1473 sanitizer = "AddressSanitizer";
1474 } else if (Sanitize.needsTsanRt()) {
1475 sanitizer = "ThreadSanitizer";
1477 if (sanitizer) {
1478 getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)
1479 << sanitizer;
1480 return;
1484 if (Sanitize.linkRuntimes()) {
1485 if (Sanitize.needsAsanRt()) {
1486 if (Sanitize.needsStableAbi()) {
1487 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);
1488 } else {
1489 assert(Sanitize.needsSharedRt() &&
1490 "Static sanitizer runtimes not supported");
1491 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
1494 if (Sanitize.needsLsanRt())
1495 AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
1496 if (Sanitize.needsUbsanRt()) {
1497 assert(Sanitize.needsSharedRt() &&
1498 "Static sanitizer runtimes not supported");
1499 AddLinkSanitizerLibArgs(
1500 Args, CmdArgs,
1501 Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");
1503 if (Sanitize.needsTsanRt()) {
1504 assert(Sanitize.needsSharedRt() &&
1505 "Static sanitizer runtimes not supported");
1506 AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
1508 if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
1509 AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
1511 // Libfuzzer is written in C++ and requires libcxx.
1512 AddCXXStdlibLibArgs(Args, CmdArgs);
1514 if (Sanitize.needsStatsRt()) {
1515 AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
1516 AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
1520 const XRayArgs &XRay = getXRayArgs();
1521 if (XRay.needsXRayRt()) {
1522 AddLinkRuntimeLib(Args, CmdArgs, "xray");
1523 AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
1524 AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
1527 if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {
1528 CmdArgs.push_back("-framework");
1529 CmdArgs.push_back("DriverKit");
1532 // Otherwise link libSystem, then the dynamic runtime library, and finally any
1533 // target specific static runtime library.
1534 if (!isTargetDriverKit())
1535 CmdArgs.push_back("-lSystem");
1537 // Select the dynamic runtime library and the target specific static library.
1538 if (isTargetIOSBased()) {
1539 // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
1540 // it never went into the SDK.
1541 // Linking against libgcc_s.1 isn't needed for iOS 5.0+
1542 if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
1543 getTriple().getArch() != llvm::Triple::aarch64)
1544 CmdArgs.push_back("-lgcc_s.1");
1546 AddLinkRuntimeLib(Args, CmdArgs, "builtins");
1549 /// Returns the most appropriate macOS target version for the current process.
1551 /// If the macOS SDK version is the same or earlier than the system version,
1552 /// then the SDK version is returned. Otherwise the system version is returned.
1553 static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
1554 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
1555 if (!SystemTriple.isMacOSX())
1556 return std::string(MacOSSDKVersion);
1557 VersionTuple SystemVersion;
1558 SystemTriple.getMacOSXVersion(SystemVersion);
1560 unsigned Major, Minor, Micro;
1561 bool HadExtra;
1562 if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
1563 HadExtra))
1564 return std::string(MacOSSDKVersion);
1565 VersionTuple SDKVersion(Major, Minor, Micro);
1567 if (SDKVersion > SystemVersion)
1568 return SystemVersion.getAsString();
1569 return std::string(MacOSSDKVersion);
1572 namespace {
1574 /// The Darwin OS that was selected or inferred from arguments / environment.
1575 struct DarwinPlatform {
1576 enum SourceKind {
1577 /// The OS was specified using the -target argument.
1578 TargetArg,
1579 /// The OS was specified using the -mtargetos= argument.
1580 MTargetOSArg,
1581 /// The OS was specified using the -m<os>-version-min argument.
1582 OSVersionArg,
1583 /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
1584 DeploymentTargetEnv,
1585 /// The OS was inferred from the SDK.
1586 InferredFromSDK,
1587 /// The OS was inferred from the -arch.
1588 InferredFromArch
1591 using DarwinPlatformKind = Darwin::DarwinPlatformKind;
1592 using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;
1594 DarwinPlatformKind getPlatform() const { return Platform; }
1596 DarwinEnvironmentKind getEnvironment() const { return Environment; }
1598 void setEnvironment(DarwinEnvironmentKind Kind) {
1599 Environment = Kind;
1600 InferSimulatorFromArch = false;
1603 StringRef getOSVersion() const {
1604 if (Kind == OSVersionArg)
1605 return Argument->getValue();
1606 return OSVersion;
1609 void setOSVersion(StringRef S) {
1610 assert(Kind == TargetArg && "Unexpected kind!");
1611 OSVersion = std::string(S);
1614 bool hasOSVersion() const { return HasOSVersion; }
1616 VersionTuple getNativeTargetVersion() const {
1617 assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
1618 "native target version is specified only for Mac Catalyst");
1619 return NativeTargetVersion;
1622 /// Returns true if the target OS was explicitly specified.
1623 bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
1625 /// Returns true if the simulator environment can be inferred from the arch.
1626 bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
1628 const std::optional<llvm::Triple> &getTargetVariantTriple() const {
1629 return TargetVariantTriple;
1632 /// Adds the -m<os>-version-min argument to the compiler invocation.
1633 void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
1634 if (Argument)
1635 return;
1636 assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&
1637 "Invalid kind");
1638 options::ID Opt;
1639 switch (Platform) {
1640 case DarwinPlatformKind::MacOS:
1641 Opt = options::OPT_mmacos_version_min_EQ;
1642 break;
1643 case DarwinPlatformKind::IPhoneOS:
1644 Opt = options::OPT_mios_version_min_EQ;
1645 break;
1646 case DarwinPlatformKind::TvOS:
1647 Opt = options::OPT_mtvos_version_min_EQ;
1648 break;
1649 case DarwinPlatformKind::WatchOS:
1650 Opt = options::OPT_mwatchos_version_min_EQ;
1651 break;
1652 case DarwinPlatformKind::DriverKit:
1653 // DriverKit always explicitly provides a version in the triple.
1654 return;
1656 Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
1657 Args.append(Argument);
1660 /// Returns the OS version with the argument / environment variable that
1661 /// specified it.
1662 std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
1663 switch (Kind) {
1664 case TargetArg:
1665 case MTargetOSArg:
1666 case OSVersionArg:
1667 case InferredFromSDK:
1668 case InferredFromArch:
1669 assert(Argument && "OS version argument not yet inferred");
1670 return Argument->getAsString(Args);
1671 case DeploymentTargetEnv:
1672 return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
1674 llvm_unreachable("Unsupported Darwin Source Kind");
1677 void setEnvironment(llvm::Triple::EnvironmentType EnvType,
1678 const VersionTuple &OSVersion,
1679 const std::optional<DarwinSDKInfo> &SDKInfo) {
1680 switch (EnvType) {
1681 case llvm::Triple::Simulator:
1682 Environment = DarwinEnvironmentKind::Simulator;
1683 break;
1684 case llvm::Triple::MacABI: {
1685 Environment = DarwinEnvironmentKind::MacCatalyst;
1686 // The minimum native macOS target for MacCatalyst is macOS 10.15.
1687 NativeTargetVersion = VersionTuple(10, 15);
1688 if (HasOSVersion && SDKInfo) {
1689 if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
1690 DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
1691 if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
1692 OSVersion, NativeTargetVersion, std::nullopt)) {
1693 NativeTargetVersion = *MacOSVersion;
1697 // In a zippered build, we could be building for a macOS target that's
1698 // lower than the version that's implied by the OS version. In that case
1699 // we need to use the minimum version as the native target version.
1700 if (TargetVariantTriple) {
1701 auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
1702 if (TargetVariantVersion.getMajor()) {
1703 if (TargetVariantVersion < NativeTargetVersion)
1704 NativeTargetVersion = TargetVariantVersion;
1707 break;
1709 default:
1710 break;
1714 static DarwinPlatform
1715 createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
1716 std::optional<llvm::Triple> TargetVariantTriple,
1717 const std::optional<DarwinSDKInfo> &SDKInfo) {
1718 DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
1720 VersionTuple OsVersion = TT.getOSVersion();
1721 if (OsVersion.getMajor() == 0)
1722 Result.HasOSVersion = false;
1723 Result.TargetVariantTriple = TargetVariantTriple;
1724 Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
1725 return Result;
1727 static DarwinPlatform
1728 createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
1729 llvm::Triple::EnvironmentType Environment, Arg *A,
1730 const std::optional<DarwinSDKInfo> &SDKInfo) {
1731 DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
1732 OSVersion.getAsString(), A);
1733 Result.InferSimulatorFromArch = false;
1734 Result.setEnvironment(Environment, OSVersion, SDKInfo);
1735 return Result;
1737 static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
1738 bool IsSimulator) {
1739 DarwinPlatform Result{OSVersionArg, Platform, A};
1740 if (IsSimulator)
1741 Result.Environment = DarwinEnvironmentKind::Simulator;
1742 return Result;
1744 static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
1745 StringRef EnvVarName,
1746 StringRef Value) {
1747 DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
1748 Result.EnvVarName = EnvVarName;
1749 return Result;
1751 static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
1752 StringRef Value,
1753 bool IsSimulator = false) {
1754 DarwinPlatform Result(InferredFromSDK, Platform, Value);
1755 if (IsSimulator)
1756 Result.Environment = DarwinEnvironmentKind::Simulator;
1757 Result.InferSimulatorFromArch = false;
1758 return Result;
1760 static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
1761 StringRef Value) {
1762 return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
1765 /// Constructs an inferred SDKInfo value based on the version inferred from
1766 /// the SDK path itself. Only works for values that were created by inferring
1767 /// the platform from the SDKPath.
1768 DarwinSDKInfo inferSDKInfo() {
1769 assert(Kind == InferredFromSDK && "can infer SDK info only");
1770 llvm::VersionTuple Version;
1771 bool IsValid = !Version.tryParse(OSVersion);
1772 (void)IsValid;
1773 assert(IsValid && "invalid SDK version");
1774 return DarwinSDKInfo(
1775 Version,
1776 /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));
1779 private:
1780 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
1781 : Kind(Kind), Platform(Platform), Argument(Argument) {}
1782 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
1783 Arg *Argument = nullptr)
1784 : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
1786 static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
1787 switch (OS) {
1788 case llvm::Triple::Darwin:
1789 case llvm::Triple::MacOSX:
1790 return DarwinPlatformKind::MacOS;
1791 case llvm::Triple::IOS:
1792 return DarwinPlatformKind::IPhoneOS;
1793 case llvm::Triple::TvOS:
1794 return DarwinPlatformKind::TvOS;
1795 case llvm::Triple::WatchOS:
1796 return DarwinPlatformKind::WatchOS;
1797 case llvm::Triple::DriverKit:
1798 return DarwinPlatformKind::DriverKit;
1799 default:
1800 llvm_unreachable("Unable to infer Darwin variant");
1804 SourceKind Kind;
1805 DarwinPlatformKind Platform;
1806 DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
1807 VersionTuple NativeTargetVersion;
1808 std::string OSVersion;
1809 bool HasOSVersion = true, InferSimulatorFromArch = true;
1810 Arg *Argument;
1811 StringRef EnvVarName;
1812 std::optional<llvm::Triple> TargetVariantTriple;
1815 /// Returns the deployment target that's specified using the -m<os>-version-min
1816 /// argument.
1817 std::optional<DarwinPlatform>
1818 getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
1819 const Driver &TheDriver) {
1820 Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
1821 Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
1822 options::OPT_mios_simulator_version_min_EQ);
1823 Arg *TvOSVersion =
1824 Args.getLastArg(options::OPT_mtvos_version_min_EQ,
1825 options::OPT_mtvos_simulator_version_min_EQ);
1826 Arg *WatchOSVersion =
1827 Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
1828 options::OPT_mwatchos_simulator_version_min_EQ);
1829 if (macOSVersion) {
1830 if (iOSVersion || TvOSVersion || WatchOSVersion) {
1831 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1832 << macOSVersion->getAsString(Args)
1833 << (iOSVersion ? iOSVersion
1834 : TvOSVersion ? TvOSVersion : WatchOSVersion)
1835 ->getAsString(Args);
1837 return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,
1838 /*IsSimulator=*/false);
1839 } else if (iOSVersion) {
1840 if (TvOSVersion || WatchOSVersion) {
1841 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1842 << iOSVersion->getAsString(Args)
1843 << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
1845 return DarwinPlatform::createOSVersionArg(
1846 Darwin::IPhoneOS, iOSVersion,
1847 iOSVersion->getOption().getID() ==
1848 options::OPT_mios_simulator_version_min_EQ);
1849 } else if (TvOSVersion) {
1850 if (WatchOSVersion) {
1851 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1852 << TvOSVersion->getAsString(Args)
1853 << WatchOSVersion->getAsString(Args);
1855 return DarwinPlatform::createOSVersionArg(
1856 Darwin::TvOS, TvOSVersion,
1857 TvOSVersion->getOption().getID() ==
1858 options::OPT_mtvos_simulator_version_min_EQ);
1859 } else if (WatchOSVersion)
1860 return DarwinPlatform::createOSVersionArg(
1861 Darwin::WatchOS, WatchOSVersion,
1862 WatchOSVersion->getOption().getID() ==
1863 options::OPT_mwatchos_simulator_version_min_EQ);
1864 return std::nullopt;
1867 /// Returns the deployment target that's specified using the
1868 /// OS_DEPLOYMENT_TARGET environment variable.
1869 std::optional<DarwinPlatform>
1870 getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
1871 const llvm::Triple &Triple) {
1872 std::string Targets[Darwin::LastDarwinPlatform + 1];
1873 const char *EnvVars[] = {
1874 "MACOSX_DEPLOYMENT_TARGET",
1875 "IPHONEOS_DEPLOYMENT_TARGET",
1876 "TVOS_DEPLOYMENT_TARGET",
1877 "WATCHOS_DEPLOYMENT_TARGET",
1878 "DRIVERKIT_DEPLOYMENT_TARGET",
1880 static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,
1881 "Missing platform");
1882 for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {
1883 if (char *Env = ::getenv(I.value()))
1884 Targets[I.index()] = Env;
1887 // Allow conflicts among OSX and iOS for historical reasons, but choose the
1888 // default platform.
1889 if (!Targets[Darwin::MacOS].empty() &&
1890 (!Targets[Darwin::IPhoneOS].empty() ||
1891 !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) {
1892 if (Triple.getArch() == llvm::Triple::arm ||
1893 Triple.getArch() == llvm::Triple::aarch64 ||
1894 Triple.getArch() == llvm::Triple::thumb)
1895 Targets[Darwin::MacOS] = "";
1896 else
1897 Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
1898 Targets[Darwin::TvOS] = "";
1899 } else {
1900 // Don't allow conflicts in any other platform.
1901 unsigned FirstTarget = std::size(Targets);
1902 for (unsigned I = 0; I != std::size(Targets); ++I) {
1903 if (Targets[I].empty())
1904 continue;
1905 if (FirstTarget == std::size(Targets))
1906 FirstTarget = I;
1907 else
1908 TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
1909 << Targets[FirstTarget] << Targets[I];
1913 for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {
1914 if (!Target.value().empty())
1915 return DarwinPlatform::createDeploymentTargetEnv(
1916 (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
1917 Target.value());
1919 return std::nullopt;
1922 /// Returns the SDK name without the optional prefix that ends with a '.' or an
1923 /// empty string otherwise.
1924 static StringRef dropSDKNamePrefix(StringRef SDKName) {
1925 size_t PrefixPos = SDKName.find('.');
1926 if (PrefixPos == StringRef::npos)
1927 return "";
1928 return SDKName.substr(PrefixPos + 1);
1931 /// Tries to infer the deployment target from the SDK specified by -isysroot
1932 /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
1933 /// it's available.
1934 std::optional<DarwinPlatform>
1935 inferDeploymentTargetFromSDK(DerivedArgList &Args,
1936 const std::optional<DarwinSDKInfo> &SDKInfo) {
1937 const Arg *A = Args.getLastArg(options::OPT_isysroot);
1938 if (!A)
1939 return std::nullopt;
1940 StringRef isysroot = A->getValue();
1941 StringRef SDK = Darwin::getSDKName(isysroot);
1942 if (!SDK.size())
1943 return std::nullopt;
1945 std::string Version;
1946 if (SDKInfo) {
1947 // Get the version from the SDKSettings.json if it's available.
1948 Version = SDKInfo->getVersion().getAsString();
1949 } else {
1950 // Slice the version number out.
1951 // Version number is between the first and the last number.
1952 size_t StartVer = SDK.find_first_of("0123456789");
1953 size_t EndVer = SDK.find_last_of("0123456789");
1954 if (StartVer != StringRef::npos && EndVer > StartVer)
1955 Version = std::string(SDK.slice(StartVer, EndVer + 1));
1957 if (Version.empty())
1958 return std::nullopt;
1960 auto CreatePlatformFromSDKName =
1961 [&](StringRef SDK) -> std::optional<DarwinPlatform> {
1962 if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
1963 return DarwinPlatform::createFromSDK(
1964 Darwin::IPhoneOS, Version,
1965 /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
1966 else if (SDK.startswith("MacOSX"))
1967 return DarwinPlatform::createFromSDK(Darwin::MacOS,
1968 getSystemOrSDKMacOSVersion(Version));
1969 else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
1970 return DarwinPlatform::createFromSDK(
1971 Darwin::WatchOS, Version,
1972 /*IsSimulator=*/SDK.startswith("WatchSimulator"));
1973 else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
1974 return DarwinPlatform::createFromSDK(
1975 Darwin::TvOS, Version,
1976 /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
1977 else if (SDK.startswith("DriverKit"))
1978 return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);
1979 return std::nullopt;
1981 if (auto Result = CreatePlatformFromSDKName(SDK))
1982 return Result;
1983 // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
1984 return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
1987 std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
1988 const Driver &TheDriver) {
1989 VersionTuple OsVersion;
1990 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
1991 switch (OS) {
1992 case llvm::Triple::Darwin:
1993 case llvm::Triple::MacOSX:
1994 // If there is no version specified on triple, and both host and target are
1995 // macos, use the host triple to infer OS version.
1996 if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
1997 !Triple.getOSMajorVersion())
1998 SystemTriple.getMacOSXVersion(OsVersion);
1999 else if (!Triple.getMacOSXVersion(OsVersion))
2000 TheDriver.Diag(diag::err_drv_invalid_darwin_version)
2001 << Triple.getOSName();
2002 break;
2003 case llvm::Triple::IOS:
2004 if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
2005 OsVersion = VersionTuple(13, 1);
2006 } else
2007 OsVersion = Triple.getiOSVersion();
2008 break;
2009 case llvm::Triple::TvOS:
2010 OsVersion = Triple.getOSVersion();
2011 break;
2012 case llvm::Triple::WatchOS:
2013 OsVersion = Triple.getWatchOSVersion();
2014 break;
2015 case llvm::Triple::DriverKit:
2016 OsVersion = Triple.getDriverKitVersion();
2017 break;
2018 default:
2019 llvm_unreachable("Unexpected OS type");
2020 break;
2023 std::string OSVersion;
2024 llvm::raw_string_ostream(OSVersion)
2025 << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
2026 << OsVersion.getSubminor().value_or(0);
2027 return OSVersion;
2030 /// Tries to infer the target OS from the -arch.
2031 std::optional<DarwinPlatform>
2032 inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
2033 const llvm::Triple &Triple,
2034 const Driver &TheDriver) {
2035 llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
2037 StringRef MachOArchName = Toolchain.getMachOArchName(Args);
2038 if (MachOArchName == "arm64" || MachOArchName == "arm64e")
2039 OSTy = llvm::Triple::MacOSX;
2040 else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
2041 OSTy = llvm::Triple::IOS;
2042 else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
2043 OSTy = llvm::Triple::WatchOS;
2044 else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
2045 MachOArchName != "armv7em")
2046 OSTy = llvm::Triple::MacOSX;
2047 if (OSTy == llvm::Triple::UnknownOS)
2048 return std::nullopt;
2049 return DarwinPlatform::createFromArch(OSTy,
2050 getOSVersion(OSTy, Triple, TheDriver));
2053 /// Returns the deployment target that's specified using the -target option.
2054 std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
2055 DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
2056 const std::optional<DarwinSDKInfo> &SDKInfo) {
2057 if (!Args.hasArg(options::OPT_target))
2058 return std::nullopt;
2059 if (Triple.getOS() == llvm::Triple::Darwin ||
2060 Triple.getOS() == llvm::Triple::UnknownOS)
2061 return std::nullopt;
2062 std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
2063 std::optional<llvm::Triple> TargetVariantTriple;
2064 for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
2065 llvm::Triple TVT(A->getValue());
2066 // Find a matching <arch>-<vendor> target variant triple that can be used.
2067 if ((Triple.getArch() == llvm::Triple::aarch64 ||
2068 TVT.getArchName() == Triple.getArchName()) &&
2069 TVT.getArch() == Triple.getArch() &&
2070 TVT.getSubArch() == Triple.getSubArch() &&
2071 TVT.getVendor() == Triple.getVendor()) {
2072 if (TargetVariantTriple)
2073 continue;
2074 A->claim();
2075 // Accept a -target-variant triple when compiling code that may run on
2076 // macOS or Mac Catalust.
2077 if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
2078 TVT.isMacCatalystEnvironment()) ||
2079 (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
2080 Triple.isMacCatalystEnvironment())) {
2081 TargetVariantTriple = TVT;
2082 continue;
2084 TheDriver.Diag(diag::err_drv_target_variant_invalid)
2085 << A->getSpelling() << A->getValue();
2088 return DarwinPlatform::createFromTarget(Triple, OSVersion,
2089 Args.getLastArg(options::OPT_target),
2090 TargetVariantTriple, SDKInfo);
2093 /// Returns the deployment target that's specified using the -mtargetos option.
2094 std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
2095 DerivedArgList &Args, const Driver &TheDriver,
2096 const std::optional<DarwinSDKInfo> &SDKInfo) {
2097 auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
2098 if (!A)
2099 return std::nullopt;
2100 llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
2101 switch (TT.getOS()) {
2102 case llvm::Triple::MacOSX:
2103 case llvm::Triple::IOS:
2104 case llvm::Triple::TvOS:
2105 case llvm::Triple::WatchOS:
2106 break;
2107 default:
2108 TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
2109 << TT.getOSName() << A->getAsString(Args);
2110 return std::nullopt;
2113 VersionTuple Version = TT.getOSVersion();
2114 if (!Version.getMajor()) {
2115 TheDriver.Diag(diag::err_drv_invalid_version_number)
2116 << A->getAsString(Args);
2117 return std::nullopt;
2119 return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,
2120 TT.getEnvironment(), A, SDKInfo);
2123 std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
2124 const ArgList &Args,
2125 const Driver &TheDriver) {
2126 const Arg *A = Args.getLastArg(options::OPT_isysroot);
2127 if (!A)
2128 return std::nullopt;
2129 StringRef isysroot = A->getValue();
2130 auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
2131 if (!SDKInfoOrErr) {
2132 llvm::consumeError(SDKInfoOrErr.takeError());
2133 TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
2134 return std::nullopt;
2136 return *SDKInfoOrErr;
2139 } // namespace
2141 void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
2142 const OptTable &Opts = getDriver().getOpts();
2144 // Support allowing the SDKROOT environment variable used by xcrun and other
2145 // Xcode tools to define the default sysroot, by making it the default for
2146 // isysroot.
2147 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2148 // Warn if the path does not exist.
2149 if (!getVFS().exists(A->getValue()))
2150 getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
2151 } else {
2152 if (char *env = ::getenv("SDKROOT")) {
2153 // We only use this value as the default if it is an absolute path,
2154 // exists, and it is not the root path.
2155 if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
2156 StringRef(env) != "/") {
2157 Args.append(Args.MakeSeparateArg(
2158 nullptr, Opts.getOption(options::OPT_isysroot), env));
2163 // Read the SDKSettings.json file for more information, like the SDK version
2164 // that we can pass down to the compiler.
2165 SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
2167 // The OS and the version can be specified using the -target argument.
2168 std::optional<DarwinPlatform> OSTarget =
2169 getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
2170 if (OSTarget) {
2171 // Disallow mixing -target and -mtargetos=.
2172 if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
2173 std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
2174 std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
2175 getDriver().Diag(diag::err_drv_cannot_mix_options)
2176 << TargetArgStr << MTargetOSArgStr;
2178 std::optional<DarwinPlatform> OSVersionArgTarget =
2179 getDeploymentTargetFromOSVersionArg(Args, getDriver());
2180 if (OSVersionArgTarget) {
2181 unsigned TargetMajor, TargetMinor, TargetMicro;
2182 bool TargetExtra;
2183 unsigned ArgMajor, ArgMinor, ArgMicro;
2184 bool ArgExtra;
2185 if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
2186 (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
2187 TargetMinor, TargetMicro, TargetExtra) &&
2188 Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
2189 ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
2190 (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
2191 VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
2192 TargetExtra != ArgExtra))) {
2193 // Select the OS version from the -m<os>-version-min argument when
2194 // the -target does not include an OS version.
2195 if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
2196 !OSTarget->hasOSVersion()) {
2197 OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
2198 } else {
2199 // Warn about -m<os>-version-min that doesn't match the OS version
2200 // that's specified in the target.
2201 std::string OSVersionArg =
2202 OSVersionArgTarget->getAsString(Args, Opts);
2203 std::string TargetArg = OSTarget->getAsString(Args, Opts);
2204 getDriver().Diag(clang::diag::warn_drv_overriding_option)
2205 << OSVersionArg << TargetArg;
2209 } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
2210 SDKInfo))) {
2211 // The OS target can be specified using the -mtargetos= argument.
2212 // Disallow mixing -mtargetos= and -m<os>version-min=.
2213 std::optional<DarwinPlatform> OSVersionArgTarget =
2214 getDeploymentTargetFromOSVersionArg(Args, getDriver());
2215 if (OSVersionArgTarget) {
2216 std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
2217 std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);
2218 getDriver().Diag(diag::err_drv_cannot_mix_options)
2219 << MTargetOSArgStr << OSVersionArgStr;
2221 } else {
2222 // The OS target can be specified using the -m<os>version-min argument.
2223 OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
2224 // If no deployment target was specified on the command line, check for
2225 // environment defines.
2226 if (!OSTarget) {
2227 OSTarget =
2228 getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
2229 if (OSTarget) {
2230 // Don't infer simulator from the arch when the SDK is also specified.
2231 std::optional<DarwinPlatform> SDKTarget =
2232 inferDeploymentTargetFromSDK(Args, SDKInfo);
2233 if (SDKTarget)
2234 OSTarget->setEnvironment(SDKTarget->getEnvironment());
2237 // If there is no command-line argument to specify the Target version and
2238 // no environment variable defined, see if we can set the default based
2239 // on -isysroot using SDKSettings.json if it exists.
2240 if (!OSTarget) {
2241 OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
2242 /// If the target was successfully constructed from the SDK path, try to
2243 /// infer the SDK info if the SDK doesn't have it.
2244 if (OSTarget && !SDKInfo)
2245 SDKInfo = OSTarget->inferSDKInfo();
2247 // If no OS targets have been specified, try to guess platform from -target
2248 // or arch name and compute the version from the triple.
2249 if (!OSTarget)
2250 OSTarget =
2251 inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
2254 assert(OSTarget && "Unable to infer Darwin variant");
2255 OSTarget->addOSVersionMinArgument(Args, Opts);
2256 DarwinPlatformKind Platform = OSTarget->getPlatform();
2258 unsigned Major, Minor, Micro;
2259 bool HadExtra;
2260 // The major version should not be over this number.
2261 const unsigned MajorVersionLimit = 1000;
2262 // Set the tool chain target information.
2263 if (Platform == MacOS) {
2264 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2265 Micro, HadExtra) ||
2266 HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
2267 Micro >= 100)
2268 getDriver().Diag(diag::err_drv_invalid_version_number)
2269 << OSTarget->getAsString(Args, Opts);
2270 } else if (Platform == IPhoneOS) {
2271 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2272 Micro, HadExtra) ||
2273 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2274 getDriver().Diag(diag::err_drv_invalid_version_number)
2275 << OSTarget->getAsString(Args, Opts);
2277 if (OSTarget->getEnvironment() == MacCatalyst &&
2278 (Major < 13 || (Major == 13 && Minor < 1))) {
2279 getDriver().Diag(diag::err_drv_invalid_version_number)
2280 << OSTarget->getAsString(Args, Opts);
2281 Major = 13;
2282 Minor = 1;
2283 Micro = 0;
2285 // For 32-bit targets, the deployment target for iOS has to be earlier than
2286 // iOS 11.
2287 if (getTriple().isArch32Bit() && Major >= 11) {
2288 // If the deployment target is explicitly specified, print a diagnostic.
2289 if (OSTarget->isExplicitlySpecified()) {
2290 if (OSTarget->getEnvironment() == MacCatalyst)
2291 getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
2292 else
2293 getDriver().Diag(diag::warn_invalid_ios_deployment_target)
2294 << OSTarget->getAsString(Args, Opts);
2295 // Otherwise, set it to 10.99.99.
2296 } else {
2297 Major = 10;
2298 Minor = 99;
2299 Micro = 99;
2302 } else if (Platform == TvOS) {
2303 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2304 Micro, HadExtra) ||
2305 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2306 getDriver().Diag(diag::err_drv_invalid_version_number)
2307 << OSTarget->getAsString(Args, Opts);
2308 } else if (Platform == WatchOS) {
2309 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2310 Micro, HadExtra) ||
2311 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2312 getDriver().Diag(diag::err_drv_invalid_version_number)
2313 << OSTarget->getAsString(Args, Opts);
2314 } else if (Platform == DriverKit) {
2315 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2316 Micro, HadExtra) ||
2317 HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
2318 Micro >= 100)
2319 getDriver().Diag(diag::err_drv_invalid_version_number)
2320 << OSTarget->getAsString(Args, Opts);
2321 } else
2322 llvm_unreachable("unknown kind of Darwin platform");
2324 DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
2325 // Recognize iOS targets with an x86 architecture as the iOS simulator.
2326 if (Environment == NativeEnvironment && Platform != MacOS &&
2327 Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
2328 getTriple().isX86())
2329 Environment = Simulator;
2331 VersionTuple NativeTargetVersion;
2332 if (Environment == MacCatalyst)
2333 NativeTargetVersion = OSTarget->getNativeTargetVersion();
2334 setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
2335 TargetVariantTriple = OSTarget->getTargetVariantTriple();
2337 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2338 StringRef SDK = getSDKName(A->getValue());
2339 if (SDK.size() > 0) {
2340 size_t StartVer = SDK.find_first_of("0123456789");
2341 StringRef SDKName = SDK.slice(0, StartVer);
2342 if (!SDKName.startswith(getPlatformFamily()) &&
2343 !dropSDKNamePrefix(SDKName).startswith(getPlatformFamily()))
2344 getDriver().Diag(diag::warn_incompatible_sysroot)
2345 << SDKName << getPlatformFamily();
2350 // For certain platforms/environments almost all resources (e.g., headers) are
2351 // located in sub-directories, e.g., for DriverKit they live in
2352 // <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).
2353 static void AppendPlatformPrefix(SmallString<128> &Path,
2354 const llvm::Triple &T) {
2355 if (T.isDriverKit()) {
2356 llvm::sys::path::append(Path, "System", "DriverKit");
2360 // Returns the effective sysroot from either -isysroot or --sysroot, plus the
2361 // platform prefix (if any).
2362 llvm::SmallString<128>
2363 DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2364 llvm::SmallString<128> Path("/");
2365 if (DriverArgs.hasArg(options::OPT_isysroot))
2366 Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
2367 else if (!getDriver().SysRoot.empty())
2368 Path = getDriver().SysRoot;
2370 if (hasEffectiveTriple()) {
2371 AppendPlatformPrefix(Path, getEffectiveTriple());
2373 return Path;
2376 void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2377 llvm::opt::ArgStringList &CC1Args) const {
2378 const Driver &D = getDriver();
2380 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2382 bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
2383 bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
2384 bool NoBuiltinInc = DriverArgs.hasFlag(
2385 options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
2386 bool ForceBuiltinInc = DriverArgs.hasFlag(
2387 options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
2389 // Add <sysroot>/usr/local/include
2390 if (!NoStdInc && !NoStdlibInc) {
2391 SmallString<128> P(Sysroot);
2392 llvm::sys::path::append(P, "usr", "local", "include");
2393 addSystemInclude(DriverArgs, CC1Args, P);
2396 // Add the Clang builtin headers (<resource>/include)
2397 if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
2398 SmallString<128> P(D.ResourceDir);
2399 llvm::sys::path::append(P, "include");
2400 addSystemInclude(DriverArgs, CC1Args, P);
2403 if (NoStdInc || NoStdlibInc)
2404 return;
2406 // Check for configure-time C include directories.
2407 llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
2408 if (!CIncludeDirs.empty()) {
2409 llvm::SmallVector<llvm::StringRef, 5> dirs;
2410 CIncludeDirs.split(dirs, ":");
2411 for (llvm::StringRef dir : dirs) {
2412 llvm::StringRef Prefix =
2413 llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
2414 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
2416 } else {
2417 // Otherwise, add <sysroot>/usr/include.
2418 SmallString<128> P(Sysroot);
2419 llvm::sys::path::append(P, "usr", "include");
2420 addExternCSystemInclude(DriverArgs, CC1Args, P.str());
2424 bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
2425 llvm::opt::ArgStringList &CC1Args,
2426 llvm::SmallString<128> Base,
2427 llvm::StringRef Version,
2428 llvm::StringRef ArchDir,
2429 llvm::StringRef BitDir) const {
2430 llvm::sys::path::append(Base, Version);
2432 // Add the base dir
2433 addSystemInclude(DriverArgs, CC1Args, Base);
2435 // Add the multilib dirs
2437 llvm::SmallString<128> P = Base;
2438 if (!ArchDir.empty())
2439 llvm::sys::path::append(P, ArchDir);
2440 if (!BitDir.empty())
2441 llvm::sys::path::append(P, BitDir);
2442 addSystemInclude(DriverArgs, CC1Args, P);
2445 // Add the backward dir
2447 llvm::SmallString<128> P = Base;
2448 llvm::sys::path::append(P, "backward");
2449 addSystemInclude(DriverArgs, CC1Args, P);
2452 return getVFS().exists(Base);
2455 void DarwinClang::AddClangCXXStdlibIncludeArgs(
2456 const llvm::opt::ArgList &DriverArgs,
2457 llvm::opt::ArgStringList &CC1Args) const {
2458 // The implementation from a base class will pass through the -stdlib to
2459 // CC1Args.
2460 // FIXME: this should not be necessary, remove usages in the frontend
2461 // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
2462 // Also check whether this is used for setting library search paths.
2463 ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
2465 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
2466 options::OPT_nostdincxx))
2467 return;
2469 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2471 switch (GetCXXStdlibType(DriverArgs)) {
2472 case ToolChain::CST_Libcxx: {
2473 // On Darwin, libc++ can be installed in one of the following two places:
2474 // 1. Alongside the compiler in <install>/include/c++/v1
2475 // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
2477 // The precendence of paths is as listed above, i.e. we take the first path
2478 // that exists. Also note that we never include libc++ twice -- we take the
2479 // first path that exists and don't send the other paths to CC1 (otherwise
2480 // include_next could break).
2482 // Check for (1)
2483 // Get from '<install>/bin' to '<install>/include/c++/v1'.
2484 // Note that InstallBin can be relative, so we use '..' instead of
2485 // parent_path.
2486 llvm::SmallString<128> InstallBin =
2487 llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin
2488 llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
2489 if (getVFS().exists(InstallBin)) {
2490 addSystemInclude(DriverArgs, CC1Args, InstallBin);
2491 return;
2492 } else if (DriverArgs.hasArg(options::OPT_v)) {
2493 llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
2494 << "\"\n";
2497 // Otherwise, check for (2)
2498 llvm::SmallString<128> SysrootUsr = Sysroot;
2499 llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
2500 if (getVFS().exists(SysrootUsr)) {
2501 addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
2502 return;
2503 } else if (DriverArgs.hasArg(options::OPT_v)) {
2504 llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
2505 << "\"\n";
2508 // Otherwise, don't add any path.
2509 break;
2512 case ToolChain::CST_Libstdcxx:
2513 llvm::SmallString<128> UsrIncludeCxx = Sysroot;
2514 llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
2516 llvm::Triple::ArchType arch = getTriple().getArch();
2517 bool IsBaseFound = true;
2518 switch (arch) {
2519 default: break;
2521 case llvm::Triple::x86:
2522 case llvm::Triple::x86_64:
2523 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2524 "4.2.1",
2525 "i686-apple-darwin10",
2526 arch == llvm::Triple::x86_64 ? "x86_64" : "");
2527 IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2528 "4.0.0", "i686-apple-darwin8",
2529 "");
2530 break;
2532 case llvm::Triple::arm:
2533 case llvm::Triple::thumb:
2534 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2535 "4.2.1",
2536 "arm-apple-darwin10",
2537 "v7");
2538 IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2539 "4.2.1",
2540 "arm-apple-darwin10",
2541 "v6");
2542 break;
2544 case llvm::Triple::aarch64:
2545 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2546 "4.2.1",
2547 "arm64-apple-darwin10",
2548 "");
2549 break;
2552 if (!IsBaseFound) {
2553 getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2556 break;
2560 void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
2561 ArgStringList &CmdArgs) const {
2562 CXXStdlibType Type = GetCXXStdlibType(Args);
2564 switch (Type) {
2565 case ToolChain::CST_Libcxx:
2566 CmdArgs.push_back("-lc++");
2567 if (Args.hasArg(options::OPT_fexperimental_library))
2568 CmdArgs.push_back("-lc++experimental");
2569 break;
2571 case ToolChain::CST_Libstdcxx:
2572 // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
2573 // it was previously found in the gcc lib dir. However, for all the Darwin
2574 // platforms we care about it was -lstdc++.6, so we search for that
2575 // explicitly if we can't see an obvious -lstdc++ candidate.
2577 // Check in the sysroot first.
2578 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2579 SmallString<128> P(A->getValue());
2580 llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
2582 if (!getVFS().exists(P)) {
2583 llvm::sys::path::remove_filename(P);
2584 llvm::sys::path::append(P, "libstdc++.6.dylib");
2585 if (getVFS().exists(P)) {
2586 CmdArgs.push_back(Args.MakeArgString(P));
2587 return;
2592 // Otherwise, look in the root.
2593 // FIXME: This should be removed someday when we don't have to care about
2594 // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
2595 if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
2596 getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
2597 CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
2598 return;
2601 // Otherwise, let the linker search.
2602 CmdArgs.push_back("-lstdc++");
2603 break;
2607 void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
2608 ArgStringList &CmdArgs) const {
2609 // For Darwin platforms, use the compiler-rt-based support library
2610 // instead of the gcc-provided one (which is also incidentally
2611 // only present in the gcc lib dir, which makes it hard to find).
2613 SmallString<128> P(getDriver().ResourceDir);
2614 llvm::sys::path::append(P, "lib", "darwin");
2616 // Use the newer cc_kext for iOS ARM after 6.0.
2617 if (isTargetWatchOS()) {
2618 llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
2619 } else if (isTargetTvOS()) {
2620 llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
2621 } else if (isTargetIPhoneOS()) {
2622 llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
2623 } else if (isTargetDriverKit()) {
2624 // DriverKit doesn't want extra runtime support.
2625 } else {
2626 llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
2629 // For now, allow missing resource libraries to support developers who may
2630 // not have compiler-rt checked out or integrated into their build.
2631 if (getVFS().exists(P))
2632 CmdArgs.push_back(Args.MakeArgString(P));
2635 DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
2636 StringRef BoundArch,
2637 Action::OffloadKind) const {
2638 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
2639 const OptTable &Opts = getDriver().getOpts();
2641 // FIXME: We really want to get out of the tool chain level argument
2642 // translation business, as it makes the driver functionality much
2643 // more opaque. For now, we follow gcc closely solely for the
2644 // purpose of easily achieving feature parity & testability. Once we
2645 // have something that works, we should reevaluate each translation
2646 // and try to push it down into tool specific logic.
2648 for (Arg *A : Args) {
2649 if (A->getOption().matches(options::OPT_Xarch__)) {
2650 // Skip this argument unless the architecture matches either the toolchain
2651 // triple arch, or the arch being bound.
2652 StringRef XarchArch = A->getValue(0);
2653 if (!(XarchArch == getArchName() ||
2654 (!BoundArch.empty() && XarchArch == BoundArch)))
2655 continue;
2657 Arg *OriginalArg = A;
2658 TranslateXarchArgs(Args, A, DAL);
2660 // Linker input arguments require custom handling. The problem is that we
2661 // have already constructed the phase actions, so we can not treat them as
2662 // "input arguments".
2663 if (A->getOption().hasFlag(options::LinkerInput)) {
2664 // Convert the argument into individual Zlinker_input_args.
2665 for (const char *Value : A->getValues()) {
2666 DAL->AddSeparateArg(
2667 OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
2669 continue;
2673 // Sob. These is strictly gcc compatible for the time being. Apple
2674 // gcc translates options twice, which means that self-expanding
2675 // options add duplicates.
2676 switch ((options::ID)A->getOption().getID()) {
2677 default:
2678 DAL->append(A);
2679 break;
2681 case options::OPT_mkernel:
2682 case options::OPT_fapple_kext:
2683 DAL->append(A);
2684 DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
2685 break;
2687 case options::OPT_dependency_file:
2688 DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
2689 break;
2691 case options::OPT_gfull:
2692 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2693 DAL->AddFlagArg(
2694 A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
2695 break;
2697 case options::OPT_gused:
2698 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2699 DAL->AddFlagArg(
2700 A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
2701 break;
2703 case options::OPT_shared:
2704 DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
2705 break;
2707 case options::OPT_fconstant_cfstrings:
2708 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
2709 break;
2711 case options::OPT_fno_constant_cfstrings:
2712 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
2713 break;
2715 case options::OPT_Wnonportable_cfstrings:
2716 DAL->AddFlagArg(A,
2717 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
2718 break;
2720 case options::OPT_Wno_nonportable_cfstrings:
2721 DAL->AddFlagArg(
2722 A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
2723 break;
2727 // Add the arch options based on the particular spelling of -arch, to match
2728 // how the driver works.
2729 if (!BoundArch.empty()) {
2730 StringRef Name = BoundArch;
2731 const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
2732 const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);
2734 // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
2735 // which defines the list of which architectures we accept.
2736 if (Name == "ppc")
2738 else if (Name == "ppc601")
2739 DAL->AddJoinedArg(nullptr, MCpu, "601");
2740 else if (Name == "ppc603")
2741 DAL->AddJoinedArg(nullptr, MCpu, "603");
2742 else if (Name == "ppc604")
2743 DAL->AddJoinedArg(nullptr, MCpu, "604");
2744 else if (Name == "ppc604e")
2745 DAL->AddJoinedArg(nullptr, MCpu, "604e");
2746 else if (Name == "ppc750")
2747 DAL->AddJoinedArg(nullptr, MCpu, "750");
2748 else if (Name == "ppc7400")
2749 DAL->AddJoinedArg(nullptr, MCpu, "7400");
2750 else if (Name == "ppc7450")
2751 DAL->AddJoinedArg(nullptr, MCpu, "7450");
2752 else if (Name == "ppc970")
2753 DAL->AddJoinedArg(nullptr, MCpu, "970");
2755 else if (Name == "ppc64" || Name == "ppc64le")
2756 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2758 else if (Name == "i386")
2760 else if (Name == "i486")
2761 DAL->AddJoinedArg(nullptr, MArch, "i486");
2762 else if (Name == "i586")
2763 DAL->AddJoinedArg(nullptr, MArch, "i586");
2764 else if (Name == "i686")
2765 DAL->AddJoinedArg(nullptr, MArch, "i686");
2766 else if (Name == "pentium")
2767 DAL->AddJoinedArg(nullptr, MArch, "pentium");
2768 else if (Name == "pentium2")
2769 DAL->AddJoinedArg(nullptr, MArch, "pentium2");
2770 else if (Name == "pentpro")
2771 DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
2772 else if (Name == "pentIIm3")
2773 DAL->AddJoinedArg(nullptr, MArch, "pentium2");
2775 else if (Name == "x86_64" || Name == "x86_64h")
2776 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2778 else if (Name == "arm")
2779 DAL->AddJoinedArg(nullptr, MArch, "armv4t");
2780 else if (Name == "armv4t")
2781 DAL->AddJoinedArg(nullptr, MArch, "armv4t");
2782 else if (Name == "armv5")
2783 DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
2784 else if (Name == "xscale")
2785 DAL->AddJoinedArg(nullptr, MArch, "xscale");
2786 else if (Name == "armv6")
2787 DAL->AddJoinedArg(nullptr, MArch, "armv6k");
2788 else if (Name == "armv6m")
2789 DAL->AddJoinedArg(nullptr, MArch, "armv6m");
2790 else if (Name == "armv7")
2791 DAL->AddJoinedArg(nullptr, MArch, "armv7a");
2792 else if (Name == "armv7em")
2793 DAL->AddJoinedArg(nullptr, MArch, "armv7em");
2794 else if (Name == "armv7k")
2795 DAL->AddJoinedArg(nullptr, MArch, "armv7k");
2796 else if (Name == "armv7m")
2797 DAL->AddJoinedArg(nullptr, MArch, "armv7m");
2798 else if (Name == "armv7s")
2799 DAL->AddJoinedArg(nullptr, MArch, "armv7s");
2802 return DAL;
2805 void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
2806 ArgStringList &CmdArgs,
2807 bool ForceLinkBuiltinRT) const {
2808 // Embedded targets are simple at the moment, not supporting sanitizers and
2809 // with different libraries for each member of the product { static, PIC } x
2810 // { hard-float, soft-float }
2811 llvm::SmallString<32> CompilerRT = StringRef("");
2812 CompilerRT +=
2813 (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
2814 ? "hard"
2815 : "soft";
2816 CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
2818 AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
2821 bool Darwin::isAlignedAllocationUnavailable() const {
2822 llvm::Triple::OSType OS;
2824 if (isTargetMacCatalyst())
2825 return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);
2826 switch (TargetPlatform) {
2827 case MacOS: // Earlier than 10.13.
2828 OS = llvm::Triple::MacOSX;
2829 break;
2830 case IPhoneOS:
2831 OS = llvm::Triple::IOS;
2832 break;
2833 case TvOS: // Earlier than 11.0.
2834 OS = llvm::Triple::TvOS;
2835 break;
2836 case WatchOS: // Earlier than 4.0.
2837 OS = llvm::Triple::WatchOS;
2838 break;
2839 case DriverKit: // Always available.
2840 return false;
2843 return TargetVersion < alignedAllocMinVersion(OS);
2846 static bool sdkSupportsBuiltinModules(const Darwin::DarwinPlatformKind &TargetPlatform, const std::optional<DarwinSDKInfo> &SDKInfo) {
2847 if (!SDKInfo)
2848 return false;
2850 VersionTuple SDKVersion = SDKInfo->getVersion();
2851 switch (TargetPlatform) {
2852 case Darwin::MacOS:
2853 return SDKVersion >= VersionTuple(99U);
2854 case Darwin::IPhoneOS:
2855 return SDKVersion >= VersionTuple(99U);
2856 case Darwin::TvOS:
2857 return SDKVersion >= VersionTuple(99U);
2858 case Darwin::WatchOS:
2859 return SDKVersion >= VersionTuple(99U);
2860 default:
2861 return true;
2865 void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
2866 llvm::opt::ArgStringList &CC1Args,
2867 Action::OffloadKind DeviceOffloadKind) const {
2868 // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
2869 // enabled or disabled aligned allocations.
2870 if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
2871 options::OPT_fno_aligned_allocation) &&
2872 isAlignedAllocationUnavailable())
2873 CC1Args.push_back("-faligned-alloc-unavailable");
2875 addClangCC1ASTargetOptions(DriverArgs, CC1Args);
2877 // Enable compatibility mode for NSItemProviderCompletionHandler in
2878 // Foundation/NSItemProvider.h.
2879 CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
2881 // Give static local variables in inline functions hidden visibility when
2882 // -fvisibility-inlines-hidden is enabled.
2883 if (!DriverArgs.getLastArgNoClaim(
2884 options::OPT_fvisibility_inlines_hidden_static_local_var,
2885 options::OPT_fno_visibility_inlines_hidden_static_local_var))
2886 CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
2888 // Earlier versions of the darwin SDK have the C standard library headers
2889 // all together in the Darwin module. That leads to module cycles with
2890 // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
2891 // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
2892 // darwin headers are in the Darwin module, there's a module cycle Darwin ->
2893 // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
2894 // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
2895 // but until then, the builtin headers need to join the system modules.
2896 // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
2897 // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
2898 // to fix the same problem with C++ headers, and is generally fragile.
2899 if (!sdkSupportsBuiltinModules(TargetPlatform, SDKInfo))
2900 CC1Args.push_back("-fbuiltin-headers-in-system-modules");
2903 void Darwin::addClangCC1ASTargetOptions(
2904 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
2905 if (TargetVariantTriple) {
2906 CC1ASArgs.push_back("-darwin-target-variant-triple");
2907 CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));
2910 if (SDKInfo) {
2911 /// Pass the SDK version to the compiler when the SDK information is
2912 /// available.
2913 auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
2914 std::string Arg;
2915 llvm::raw_string_ostream OS(Arg);
2916 OS << "-target-sdk-version=" << V;
2917 CC1ASArgs.push_back(Args.MakeArgString(OS.str()));
2920 if (isTargetMacCatalyst()) {
2921 if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
2922 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
2923 std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
2924 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
2925 std::nullopt);
2926 EmitTargetSDKVersionArg(
2927 SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
2929 } else {
2930 EmitTargetSDKVersionArg(SDKInfo->getVersion());
2933 /// Pass the target variant SDK version to the compiler when the SDK
2934 /// information is available and is required for target variant.
2935 if (TargetVariantTriple) {
2936 if (isTargetMacCatalyst()) {
2937 std::string Arg;
2938 llvm::raw_string_ostream OS(Arg);
2939 OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
2940 CC1ASArgs.push_back(Args.MakeArgString(OS.str()));
2941 } else if (const auto *MacOStoMacCatalystMapping =
2942 SDKInfo->getVersionMapping(
2943 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
2944 if (std::optional<VersionTuple> SDKVersion =
2945 MacOStoMacCatalystMapping->map(
2946 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
2947 std::nullopt)) {
2948 std::string Arg;
2949 llvm::raw_string_ostream OS(Arg);
2950 OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
2951 CC1ASArgs.push_back(Args.MakeArgString(OS.str()));
2958 DerivedArgList *
2959 Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
2960 Action::OffloadKind DeviceOffloadKind) const {
2961 // First get the generic Apple args, before moving onto Darwin-specific ones.
2962 DerivedArgList *DAL =
2963 MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
2965 // If no architecture is bound, none of the translations here are relevant.
2966 if (BoundArch.empty())
2967 return DAL;
2969 // Add an explicit version min argument for the deployment target. We do this
2970 // after argument translation because -Xarch_ arguments may add a version min
2971 // argument.
2972 AddDeploymentTarget(*DAL);
2974 // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
2975 // FIXME: It would be far better to avoid inserting those -static arguments,
2976 // but we can't check the deployment target in the translation code until
2977 // it is set here.
2978 if (isTargetWatchOSBased() || isTargetDriverKit() ||
2979 (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
2980 for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
2981 Arg *A = *it;
2982 ++it;
2983 if (A->getOption().getID() != options::OPT_mkernel &&
2984 A->getOption().getID() != options::OPT_fapple_kext)
2985 continue;
2986 assert(it != ie && "unexpected argument translation");
2987 A = *it;
2988 assert(A->getOption().getID() == options::OPT_static &&
2989 "missing expected -static argument");
2990 *it = nullptr;
2991 ++it;
2995 auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
2996 if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
2997 if (Args.hasFlag(options::OPT_fomit_frame_pointer,
2998 options::OPT_fno_omit_frame_pointer, false))
2999 getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
3000 << "-fomit-frame-pointer" << BoundArch;
3003 return DAL;
3006 ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
3007 // Unwind tables are not emitted if -fno-exceptions is supplied (except when
3008 // targeting x86_64).
3009 if (getArch() == llvm::Triple::x86_64 ||
3010 (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
3011 Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
3012 true)))
3013 return (getArch() == llvm::Triple::aarch64 ||
3014 getArch() == llvm::Triple::aarch64_32)
3015 ? UnwindTableLevel::Synchronous
3016 : UnwindTableLevel::Asynchronous;
3018 return UnwindTableLevel::None;
3021 bool MachO::UseDwarfDebugFlags() const {
3022 if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
3023 return S[0] != '\0';
3024 return false;
3027 std::string MachO::GetGlobalDebugPathRemapping() const {
3028 if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))
3029 return S;
3030 return {};
3033 llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
3034 // Darwin uses SjLj exceptions on ARM.
3035 if (getTriple().getArch() != llvm::Triple::arm &&
3036 getTriple().getArch() != llvm::Triple::thumb)
3037 return llvm::ExceptionHandling::None;
3039 // Only watchOS uses the new DWARF/Compact unwinding method.
3040 llvm::Triple Triple(ComputeLLVMTriple(Args));
3041 if (Triple.isWatchABI())
3042 return llvm::ExceptionHandling::DwarfCFI;
3044 return llvm::ExceptionHandling::SjLj;
3047 bool Darwin::SupportsEmbeddedBitcode() const {
3048 assert(TargetInitialized && "Target not initialized!");
3049 if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
3050 return false;
3051 return true;
3054 bool MachO::isPICDefault() const { return true; }
3056 bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
3058 bool MachO::isPICDefaultForced() const {
3059 return (getArch() == llvm::Triple::x86_64 ||
3060 getArch() == llvm::Triple::aarch64);
3063 bool MachO::SupportsProfiling() const {
3064 // Profiling instrumentation is only supported on x86.
3065 return getTriple().isX86();
3068 void Darwin::addMinVersionArgs(const ArgList &Args,
3069 ArgStringList &CmdArgs) const {
3070 VersionTuple TargetVersion = getTripleTargetVersion();
3072 if (isTargetWatchOS())
3073 CmdArgs.push_back("-watchos_version_min");
3074 else if (isTargetWatchOSSimulator())
3075 CmdArgs.push_back("-watchos_simulator_version_min");
3076 else if (isTargetTvOS())
3077 CmdArgs.push_back("-tvos_version_min");
3078 else if (isTargetTvOSSimulator())
3079 CmdArgs.push_back("-tvos_simulator_version_min");
3080 else if (isTargetDriverKit())
3081 CmdArgs.push_back("-driverkit_version_min");
3082 else if (isTargetIOSSimulator())
3083 CmdArgs.push_back("-ios_simulator_version_min");
3084 else if (isTargetIOSBased())
3085 CmdArgs.push_back("-iphoneos_version_min");
3086 else if (isTargetMacCatalyst())
3087 CmdArgs.push_back("-maccatalyst_version_min");
3088 else {
3089 assert(isTargetMacOS() && "unexpected target");
3090 CmdArgs.push_back("-macosx_version_min");
3093 VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
3094 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3095 TargetVersion = MinTgtVers;
3096 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3097 if (TargetVariantTriple) {
3098 assert(isTargetMacOSBased() && "unexpected target");
3099 VersionTuple VariantTargetVersion;
3100 if (TargetVariantTriple->isMacOSX()) {
3101 CmdArgs.push_back("-macosx_version_min");
3102 TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);
3103 } else {
3104 assert(TargetVariantTriple->isiOS() &&
3105 TargetVariantTriple->isMacCatalystEnvironment() &&
3106 "unexpected target variant triple");
3107 CmdArgs.push_back("-maccatalyst_version_min");
3108 VariantTargetVersion = TargetVariantTriple->getiOSVersion();
3110 VersionTuple MinTgtVers =
3111 TargetVariantTriple->getMinimumSupportedOSVersion();
3112 if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
3113 VariantTargetVersion = MinTgtVers;
3114 CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));
3118 static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
3119 Darwin::DarwinEnvironmentKind Environment) {
3120 switch (Platform) {
3121 case Darwin::MacOS:
3122 return "macos";
3123 case Darwin::IPhoneOS:
3124 if (Environment == Darwin::MacCatalyst)
3125 return "mac catalyst";
3126 return "ios";
3127 case Darwin::TvOS:
3128 return "tvos";
3129 case Darwin::WatchOS:
3130 return "watchos";
3131 case Darwin::DriverKit:
3132 return "driverkit";
3134 llvm_unreachable("invalid platform");
3137 void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
3138 llvm::opt::ArgStringList &CmdArgs) const {
3139 auto EmitPlatformVersionArg =
3140 [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
3141 Darwin::DarwinEnvironmentKind TargetEnvironment,
3142 const llvm::Triple &TT) {
3143 // -platform_version <platform> <target_version> <sdk_version>
3144 // Both the target and SDK version support only up to 3 components.
3145 CmdArgs.push_back("-platform_version");
3146 std::string PlatformName =
3147 getPlatformName(TargetPlatform, TargetEnvironment);
3148 if (TargetEnvironment == Darwin::Simulator)
3149 PlatformName += "-simulator";
3150 CmdArgs.push_back(Args.MakeArgString(PlatformName));
3151 VersionTuple TargetVersion = TV.withoutBuild();
3152 if ((TargetPlatform == Darwin::IPhoneOS ||
3153 TargetPlatform == Darwin::TvOS) &&
3154 getTriple().getArchName() == "arm64e" &&
3155 TargetVersion.getMajor() < 14) {
3156 // arm64e slice is supported on iOS/tvOS 14+ only.
3157 TargetVersion = VersionTuple(14, 0);
3159 VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
3160 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3161 TargetVersion = MinTgtVers;
3162 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3164 if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
3165 // Mac Catalyst programs must use the appropriate iOS SDK version
3166 // that corresponds to the macOS SDK version used for the compilation.
3167 std::optional<VersionTuple> iOSSDKVersion;
3168 if (SDKInfo) {
3169 if (const auto *MacOStoMacCatalystMapping =
3170 SDKInfo->getVersionMapping(
3171 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3172 iOSSDKVersion = MacOStoMacCatalystMapping->map(
3173 SDKInfo->getVersion().withoutBuild(),
3174 minimumMacCatalystDeploymentTarget(), std::nullopt);
3177 CmdArgs.push_back(Args.MakeArgString(
3178 (iOSSDKVersion ? *iOSSDKVersion
3179 : minimumMacCatalystDeploymentTarget())
3180 .getAsString()));
3181 return;
3184 if (SDKInfo) {
3185 VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
3186 if (!SDKVersion.getMinor())
3187 SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
3188 CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
3189 } else {
3190 // Use an SDK version that's matching the deployment target if the SDK
3191 // version is missing. This is preferred over an empty SDK version
3192 // (0.0.0) as the system's runtime might expect the linked binary to
3193 // contain a valid SDK version in order for the binary to work
3194 // correctly. It's reasonable to use the deployment target version as
3195 // a proxy for the SDK version because older SDKs don't guarantee
3196 // support for deployment targets newer than the SDK versions, so that
3197 // rules out using some predetermined older SDK version, which leaves
3198 // the deployment target version as the only reasonable choice.
3199 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3202 EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
3203 TargetEnvironment, getEffectiveTriple());
3204 if (!TargetVariantTriple)
3205 return;
3206 Darwin::DarwinPlatformKind Platform;
3207 Darwin::DarwinEnvironmentKind Environment;
3208 VersionTuple TargetVariantVersion;
3209 if (TargetVariantTriple->isMacOSX()) {
3210 TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);
3211 Platform = Darwin::MacOS;
3212 Environment = Darwin::NativeEnvironment;
3213 } else {
3214 assert(TargetVariantTriple->isiOS() &&
3215 TargetVariantTriple->isMacCatalystEnvironment() &&
3216 "unexpected target variant triple");
3217 TargetVariantVersion = TargetVariantTriple->getiOSVersion();
3218 Platform = Darwin::IPhoneOS;
3219 Environment = Darwin::MacCatalyst;
3221 EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
3222 *TargetVariantTriple);
3225 // Add additional link args for the -dynamiclib option.
3226 static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
3227 ArgStringList &CmdArgs) {
3228 // Derived from darwin_dylib1 spec.
3229 if (D.isTargetIPhoneOS()) {
3230 if (D.isIPhoneOSVersionLT(3, 1))
3231 CmdArgs.push_back("-ldylib1.o");
3232 return;
3235 if (!D.isTargetMacOS())
3236 return;
3237 if (D.isMacosxVersionLT(10, 5))
3238 CmdArgs.push_back("-ldylib1.o");
3239 else if (D.isMacosxVersionLT(10, 6))
3240 CmdArgs.push_back("-ldylib1.10.5.o");
3243 // Add additional link args for the -bundle option.
3244 static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
3245 ArgStringList &CmdArgs) {
3246 if (Args.hasArg(options::OPT_static))
3247 return;
3248 // Derived from darwin_bundle1 spec.
3249 if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
3250 (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
3251 CmdArgs.push_back("-lbundle1.o");
3254 // Add additional link args for the -pg option.
3255 static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
3256 ArgStringList &CmdArgs) {
3257 if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
3258 if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
3259 Args.hasArg(options::OPT_preload)) {
3260 CmdArgs.push_back("-lgcrt0.o");
3261 } else {
3262 CmdArgs.push_back("-lgcrt1.o");
3264 // darwin_crt2 spec is empty.
3266 // By default on OS X 10.8 and later, we don't link with a crt1.o
3267 // file and the linker knows to use _main as the entry point. But,
3268 // when compiling with -pg, we need to link with the gcrt1.o file,
3269 // so pass the -no_new_main option to tell the linker to use the
3270 // "start" symbol as the entry point.
3271 if (!D.isMacosxVersionLT(10, 8))
3272 CmdArgs.push_back("-no_new_main");
3273 } else {
3274 D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
3275 << D.isTargetMacOSBased();
3279 static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
3280 ArgStringList &CmdArgs) {
3281 // Derived from darwin_crt1 spec.
3282 if (D.isTargetIPhoneOS()) {
3283 if (D.getArch() == llvm::Triple::aarch64)
3284 ; // iOS does not need any crt1 files for arm64
3285 else if (D.isIPhoneOSVersionLT(3, 1))
3286 CmdArgs.push_back("-lcrt1.o");
3287 else if (D.isIPhoneOSVersionLT(6, 0))
3288 CmdArgs.push_back("-lcrt1.3.1.o");
3289 return;
3292 if (!D.isTargetMacOS())
3293 return;
3294 if (D.isMacosxVersionLT(10, 5))
3295 CmdArgs.push_back("-lcrt1.o");
3296 else if (D.isMacosxVersionLT(10, 6))
3297 CmdArgs.push_back("-lcrt1.10.5.o");
3298 else if (D.isMacosxVersionLT(10, 8))
3299 CmdArgs.push_back("-lcrt1.10.6.o");
3300 // darwin_crt2 spec is empty.
3303 void Darwin::addStartObjectFileArgs(const ArgList &Args,
3304 ArgStringList &CmdArgs) const {
3305 // Derived from startfile spec.
3306 if (Args.hasArg(options::OPT_dynamiclib))
3307 addDynamicLibLinkArgs(*this, Args, CmdArgs);
3308 else if (Args.hasArg(options::OPT_bundle))
3309 addBundleLinkArgs(*this, Args, CmdArgs);
3310 else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
3311 addPgProfilingLinkArgs(*this, Args, CmdArgs);
3312 else if (Args.hasArg(options::OPT_static) ||
3313 Args.hasArg(options::OPT_object) ||
3314 Args.hasArg(options::OPT_preload))
3315 CmdArgs.push_back("-lcrt0.o");
3316 else
3317 addDefaultCRTLinkArgs(*this, Args, CmdArgs);
3319 if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
3320 isMacosxVersionLT(10, 5)) {
3321 const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
3322 CmdArgs.push_back(Str);
3326 void Darwin::CheckObjCARC() const {
3327 if (isTargetIOSBased() || isTargetWatchOSBased() ||
3328 (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
3329 return;
3330 getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
3333 SanitizerMask Darwin::getSupportedSanitizers() const {
3334 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
3335 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
3336 SanitizerMask Res = ToolChain::getSupportedSanitizers();
3337 Res |= SanitizerKind::Address;
3338 Res |= SanitizerKind::PointerCompare;
3339 Res |= SanitizerKind::PointerSubtract;
3340 Res |= SanitizerKind::Leak;
3341 Res |= SanitizerKind::Fuzzer;
3342 Res |= SanitizerKind::FuzzerNoLink;
3343 Res |= SanitizerKind::ObjCCast;
3345 // Prior to 10.9, macOS shipped a version of the C++ standard library without
3346 // C++11 support. The same is true of iOS prior to version 5. These OS'es are
3347 // incompatible with -fsanitize=vptr.
3348 if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&
3349 !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
3350 Res |= SanitizerKind::Vptr;
3352 if ((IsX86_64 || IsAArch64) &&
3353 (isTargetMacOSBased() || isTargetIOSSimulator() ||
3354 isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
3355 Res |= SanitizerKind::Thread;
3357 return Res;
3360 void Darwin::printVerboseInfo(raw_ostream &OS) const {
3361 CudaInstallation.print(OS);
3362 RocmInstallation.print(OS);