[Transforms] Silence a warning in SROA.cpp (NFC)
[llvm-project.git] / clang / lib / Driver / ToolChains / Darwin.cpp
blobcdb6d21a0148b6cfa0777ce81622aff00c84181d
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,
223 bool UsePlatformVersion) const {
224 const Driver &D = getToolChain().getDriver();
225 const toolchains::MachO &MachOTC = getMachOToolChain();
227 // Newer linkers support -demangle. Pass it if supported and not disabled by
228 // the user.
229 if ((Version >= VersionTuple(100) || LinkerIsLLD) &&
230 !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
231 CmdArgs.push_back("-demangle");
233 if (Args.hasArg(options::OPT_rdynamic) &&
234 (Version >= VersionTuple(137) || LinkerIsLLD))
235 CmdArgs.push_back("-export_dynamic");
237 // If we are using App Extension restrictions, pass a flag to the linker
238 // telling it that the compiled code has been audited.
239 if (Args.hasFlag(options::OPT_fapplication_extension,
240 options::OPT_fno_application_extension, false))
241 CmdArgs.push_back("-application_extension");
243 if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&
244 NeedsTempPath(Inputs)) {
245 std::string TmpPathName;
246 if (D.getLTOMode() == LTOK_Full) {
247 // If we are using full LTO, then automatically create a temporary file
248 // path for the linker to use, so that it's lifetime will extend past a
249 // possible dsymutil step.
250 TmpPathName =
251 D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
252 } else if (D.getLTOMode() == LTOK_Thin)
253 // If we are using thin LTO, then create a directory instead.
254 TmpPathName = D.GetTemporaryDirectory("thinlto");
256 if (!TmpPathName.empty()) {
257 auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
258 C.addTempFile(TmpPath);
259 CmdArgs.push_back("-object_path_lto");
260 CmdArgs.push_back(TmpPath);
264 // Use -lto_library option to specify the libLTO.dylib path. Try to find
265 // it in clang installed libraries. ld64 will only look at this argument
266 // when it actually uses LTO, so libLTO.dylib only needs to exist at link
267 // time if ld64 decides that it needs to use LTO.
268 // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
269 // next to it. That's ok since ld64 using a libLTO.dylib not matching the
270 // clang version won't work anyways.
271 // lld is built at the same revision as clang and statically links in
272 // LLVM libraries, so it doesn't need libLTO.dylib.
273 if (Version >= VersionTuple(133) && !LinkerIsLLD) {
274 // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
275 StringRef P = llvm::sys::path::parent_path(D.Dir);
276 SmallString<128> LibLTOPath(P);
277 llvm::sys::path::append(LibLTOPath, "lib");
278 llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
279 CmdArgs.push_back("-lto_library");
280 CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
283 // ld64 version 262 and above runs the deduplicate pass by default.
284 // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`
285 // if `!shouldLinkerNotDedup()` if LinkerIsLLD here?
286 if (Version >= VersionTuple(262) &&
287 shouldLinkerNotDedup(C.getJobs().empty(), Args))
288 CmdArgs.push_back("-no_deduplicate");
290 // Derived from the "link" spec.
291 Args.AddAllArgs(CmdArgs, options::OPT_static);
292 if (!Args.hasArg(options::OPT_static))
293 CmdArgs.push_back("-dynamic");
294 if (Args.hasArg(options::OPT_fgnu_runtime)) {
295 // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
296 // here. How do we wish to handle such things?
299 if (!Args.hasArg(options::OPT_dynamiclib)) {
300 AddMachOArch(Args, CmdArgs);
301 // FIXME: Why do this only on this path?
302 Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
304 Args.AddLastArg(CmdArgs, options::OPT_bundle);
305 Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
306 Args.AddAllArgs(CmdArgs, options::OPT_client__name);
308 Arg *A;
309 if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
310 (A = Args.getLastArg(options::OPT_current__version)) ||
311 (A = Args.getLastArg(options::OPT_install__name)))
312 D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
313 << "-dynamiclib";
315 Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
316 Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
317 Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
318 } else {
319 CmdArgs.push_back("-dylib");
321 Arg *A;
322 if ((A = Args.getLastArg(options::OPT_bundle)) ||
323 (A = Args.getLastArg(options::OPT_bundle__loader)) ||
324 (A = Args.getLastArg(options::OPT_client__name)) ||
325 (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
326 (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
327 (A = Args.getLastArg(options::OPT_private__bundle)))
328 D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
329 << "-dynamiclib";
331 Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
332 "-dylib_compatibility_version");
333 Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
334 "-dylib_current_version");
336 AddMachOArch(Args, CmdArgs);
338 Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
339 "-dylib_install_name");
342 Args.AddLastArg(CmdArgs, options::OPT_all__load);
343 Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
344 Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
345 if (MachOTC.isTargetIOSBased())
346 Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
347 Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
348 Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
349 Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
350 Args.AddLastArg(CmdArgs, options::OPT_dynamic);
351 Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
352 Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
353 Args.AddAllArgs(CmdArgs, options::OPT_force__load);
354 Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
355 Args.AddAllArgs(CmdArgs, options::OPT_image__base);
356 Args.AddAllArgs(CmdArgs, options::OPT_init);
358 // Add the deployment target.
359 if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)
360 MachOTC.addPlatformVersionArgs(Args, CmdArgs);
361 else
362 MachOTC.addMinVersionArgs(Args, CmdArgs);
364 Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
365 Args.AddLastArg(CmdArgs, options::OPT_multi__module);
366 Args.AddLastArg(CmdArgs, options::OPT_single__module);
367 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
368 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
370 if (const Arg *A =
371 Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
372 options::OPT_fno_pie, options::OPT_fno_PIE)) {
373 if (A->getOption().matches(options::OPT_fpie) ||
374 A->getOption().matches(options::OPT_fPIE))
375 CmdArgs.push_back("-pie");
376 else
377 CmdArgs.push_back("-no_pie");
380 // for embed-bitcode, use -bitcode_bundle in linker command
381 if (C.getDriver().embedBitcodeEnabled()) {
382 // Check if the toolchain supports bitcode build flow.
383 if (MachOTC.SupportsEmbeddedBitcode()) {
384 CmdArgs.push_back("-bitcode_bundle");
385 // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.
386 if (C.getDriver().embedBitcodeMarkerOnly() &&
387 Version >= VersionTuple(278)) {
388 CmdArgs.push_back("-bitcode_process_mode");
389 CmdArgs.push_back("marker");
391 } else
392 D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
395 // If GlobalISel is enabled, pass it through to LLVM.
396 if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
397 options::OPT_fno_global_isel)) {
398 if (A->getOption().matches(options::OPT_fglobal_isel)) {
399 CmdArgs.push_back("-mllvm");
400 CmdArgs.push_back("-global-isel");
401 // Disable abort and fall back to SDAG silently.
402 CmdArgs.push_back("-mllvm");
403 CmdArgs.push_back("-global-isel-abort=0");
407 if (Args.hasArg(options::OPT_mkernel) ||
408 Args.hasArg(options::OPT_fapple_kext) ||
409 Args.hasArg(options::OPT_ffreestanding)) {
410 CmdArgs.push_back("-mllvm");
411 CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");
414 Args.AddLastArg(CmdArgs, options::OPT_prebind);
415 Args.AddLastArg(CmdArgs, options::OPT_noprebind);
416 Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
417 Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
418 Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
419 Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
420 Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
421 Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
422 Args.AddAllArgs(CmdArgs, options::OPT_segprot);
423 Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
424 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
425 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
426 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
427 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
428 Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
429 Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
431 // Give --sysroot= preference, over the Apple specific behavior to also use
432 // --isysroot as the syslibroot.
433 // We check `OPT__sysroot_EQ` directly instead of `getSysRoot` to make sure we
434 // prioritise command line arguments over configuration of `DEFAULT_SYSROOT`.
435 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
436 CmdArgs.push_back("-syslibroot");
437 CmdArgs.push_back(A->getValue());
438 } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
439 CmdArgs.push_back("-syslibroot");
440 CmdArgs.push_back(A->getValue());
441 } else if (StringRef sysroot = C.getSysRoot(); sysroot != "") {
442 CmdArgs.push_back("-syslibroot");
443 CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
446 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
447 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
448 Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
449 Args.AddAllArgs(CmdArgs, options::OPT_undefined);
450 Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
451 Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
452 Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
453 Args.AddAllArgs(CmdArgs, options::OPT_y);
454 Args.AddLastArg(CmdArgs, options::OPT_w);
455 Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
456 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
457 Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
458 Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
459 Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
460 Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
461 Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
462 Args.AddLastArg(CmdArgs, options::OPT_why_load);
463 Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
464 Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
465 Args.AddLastArg(CmdArgs, options::OPT_dylinker);
466 Args.AddLastArg(CmdArgs, options::OPT_Mach);
468 if (LinkerIsLLD) {
469 if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
470 SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0
471 ? ""
472 : CSPGOGenerateArg->getValue());
473 llvm::sys::path::append(Path, "default_%m.profraw");
474 CmdArgs.push_back("--cs-profile-generate");
475 CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
476 } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
477 SmallString<128> Path(
478 ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
479 if (Path.empty() || llvm::sys::fs::is_directory(Path))
480 llvm::sys::path::append(Path, "default.profdata");
481 CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
484 auto *CodeGenDataGenArg =
485 Args.getLastArg(options::OPT_fcodegen_data_generate_EQ);
486 if (CodeGenDataGenArg)
487 CmdArgs.push_back(
488 Args.MakeArgString(Twine("--codegen-data-generate-path=") +
489 CodeGenDataGenArg->getValue()));
493 /// Determine whether we are linking the ObjC runtime.
494 static bool isObjCRuntimeLinked(const ArgList &Args) {
495 if (isObjCAutoRefCount(Args)) {
496 Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
497 return true;
499 return Args.hasArg(options::OPT_fobjc_link_runtime);
502 static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
503 const llvm::Triple &Triple) {
504 // When enabling remarks, we need to error if:
505 // * The remark file is specified but we're targeting multiple architectures,
506 // which means more than one remark file is being generated.
507 bool hasMultipleInvocations =
508 Args.getAllArgValues(options::OPT_arch).size() > 1;
509 bool hasExplicitOutputFile =
510 Args.getLastArg(options::OPT_foptimization_record_file_EQ);
511 if (hasMultipleInvocations && hasExplicitOutputFile) {
512 D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
513 << "-foptimization-record-file";
514 return false;
516 return true;
519 static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
520 const llvm::Triple &Triple,
521 const InputInfo &Output, const JobAction &JA) {
522 StringRef Format = "yaml";
523 if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
524 Format = A->getValue();
526 CmdArgs.push_back("-mllvm");
527 CmdArgs.push_back("-lto-pass-remarks-output");
528 CmdArgs.push_back("-mllvm");
530 const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
531 if (A) {
532 CmdArgs.push_back(A->getValue());
533 } else {
534 assert(Output.isFilename() && "Unexpected ld output.");
535 SmallString<128> F;
536 F = Output.getFilename();
537 F += ".opt.";
538 F += Format;
540 CmdArgs.push_back(Args.MakeArgString(F));
543 if (const Arg *A =
544 Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
545 CmdArgs.push_back("-mllvm");
546 std::string Passes =
547 std::string("-lto-pass-remarks-filter=") + A->getValue();
548 CmdArgs.push_back(Args.MakeArgString(Passes));
551 if (!Format.empty()) {
552 CmdArgs.push_back("-mllvm");
553 Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
554 CmdArgs.push_back(Args.MakeArgString(FormatArg));
557 if (getLastProfileUseArg(Args)) {
558 CmdArgs.push_back("-mllvm");
559 CmdArgs.push_back("-lto-pass-remarks-with-hotness");
561 if (const Arg *A =
562 Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
563 CmdArgs.push_back("-mllvm");
564 std::string Opt =
565 std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
566 CmdArgs.push_back(Args.MakeArgString(Opt));
571 static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);
573 void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
574 const InputInfo &Output,
575 const InputInfoList &Inputs,
576 const ArgList &Args,
577 const char *LinkingOutput) const {
578 assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
580 // If the number of arguments surpasses the system limits, we will encode the
581 // input files in a separate file, shortening the command line. To this end,
582 // build a list of input file names that can be passed via a file with the
583 // -filelist linker option.
584 llvm::opt::ArgStringList InputFileList;
586 // The logic here is derived from gcc's behavior; most of which
587 // comes from specs (starting with link_command). Consult gcc for
588 // more information.
589 ArgStringList CmdArgs;
591 /// Hack(tm) to ignore linking errors when we are doing ARC migration.
592 if (Args.hasArg(options::OPT_ccc_arcmt_check,
593 options::OPT_ccc_arcmt_migrate)) {
594 for (const auto &Arg : Args)
595 Arg->claim();
596 const char *Exec =
597 Args.MakeArgString(getToolChain().GetProgramPath("touch"));
598 CmdArgs.push_back(Output.getFilename());
599 C.addCommand(std::make_unique<Command>(JA, *this,
600 ResponseFileSupport::None(), Exec,
601 CmdArgs, std::nullopt, Output));
602 return;
605 VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
607 bool LinkerIsLLD;
608 const char *Exec =
609 Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));
611 // xrOS always uses -platform-version.
612 bool UsePlatformVersion = getToolChain().getTriple().isXROS();
614 // I'm not sure why this particular decomposition exists in gcc, but
615 // we follow suite for ease of comparison.
616 AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,
617 UsePlatformVersion);
619 if (willEmitRemarks(Args) &&
620 checkRemarksOptions(getToolChain().getDriver(), Args,
621 getToolChain().getTriple()))
622 renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);
624 // Propagate the -moutline flag to the linker in LTO.
625 if (Arg *A =
626 Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {
627 if (A->getOption().matches(options::OPT_moutline)) {
628 if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
629 CmdArgs.push_back("-mllvm");
630 CmdArgs.push_back("-enable-machine-outliner");
632 } else {
633 // Disable all outlining behaviour if we have mno-outline. We need to do
634 // this explicitly, because targets which support default outlining will
635 // try to do work if we don't.
636 CmdArgs.push_back("-mllvm");
637 CmdArgs.push_back("-enable-machine-outliner=never");
641 // Outline from linkonceodr functions by default in LTO, whenever the outliner
642 // is enabled. Note that the target may enable the machine outliner
643 // independently of -moutline.
644 CmdArgs.push_back("-mllvm");
645 CmdArgs.push_back("-enable-linkonceodr-outlining");
647 // Propagate codegen data flags to the linker for the LLVM backend.
648 auto *CodeGenDataGenArg =
649 Args.getLastArg(options::OPT_fcodegen_data_generate_EQ);
650 auto *CodeGenDataUseArg = Args.getLastArg(options::OPT_fcodegen_data_use_EQ);
652 // We only allow one of them to be specified.
653 const Driver &D = getToolChain().getDriver();
654 if (CodeGenDataGenArg && CodeGenDataUseArg)
655 D.Diag(diag::err_drv_argument_not_allowed_with)
656 << CodeGenDataGenArg->getAsString(Args)
657 << CodeGenDataUseArg->getAsString(Args);
659 // For codegen data gen, the output file is passed to the linker
660 // while a boolean flag is passed to the LLVM backend.
661 if (CodeGenDataGenArg) {
662 CmdArgs.push_back("-mllvm");
663 CmdArgs.push_back("-codegen-data-generate");
666 // For codegen data use, the input file is passed to the LLVM backend.
667 if (CodeGenDataUseArg) {
668 CmdArgs.push_back("-mllvm");
669 CmdArgs.push_back(Args.MakeArgString(Twine("-codegen-data-use-path=") +
670 CodeGenDataUseArg->getValue()));
673 // Setup statistics file output.
674 SmallString<128> StatsFile =
675 getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
676 if (!StatsFile.empty()) {
677 CmdArgs.push_back("-mllvm");
678 CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));
681 // It seems that the 'e' option is completely ignored for dynamic executables
682 // (the default), and with static executables, the last one wins, as expected.
683 Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
684 options::OPT_Z_Flag, options::OPT_u_Group});
686 // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
687 // members of static archive libraries which implement Objective-C classes or
688 // categories.
689 if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
690 CmdArgs.push_back("-ObjC");
692 CmdArgs.push_back("-o");
693 CmdArgs.push_back(Output.getFilename());
695 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
696 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
698 Args.AddAllArgs(CmdArgs, options::OPT_L);
700 AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
701 // Build the input file for -filelist (list of linker input files) in case we
702 // need it later
703 for (const auto &II : Inputs) {
704 if (!II.isFilename()) {
705 // This is a linker input argument.
706 // We cannot mix input arguments and file names in a -filelist input, thus
707 // we prematurely stop our list (remaining files shall be passed as
708 // arguments).
709 if (InputFileList.size() > 0)
710 break;
712 continue;
715 InputFileList.push_back(II.getFilename());
718 // Additional linker set-up and flags for Fortran. This is required in order
719 // to generate executables.
720 if (getToolChain().getDriver().IsFlangMode() &&
721 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
722 addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
723 addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
726 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
727 addOpenMPRuntime(C, CmdArgs, getToolChain(), Args);
729 if (isObjCRuntimeLinked(Args) &&
730 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
731 // We use arclite library for both ARC and subscripting support.
732 getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
734 CmdArgs.push_back("-framework");
735 CmdArgs.push_back("Foundation");
736 // Link libobj.
737 CmdArgs.push_back("-lobjc");
740 if (LinkingOutput) {
741 CmdArgs.push_back("-arch_multiple");
742 CmdArgs.push_back("-final_output");
743 CmdArgs.push_back(LinkingOutput);
746 if (Args.hasArg(options::OPT_fnested_functions))
747 CmdArgs.push_back("-allow_stack_execute");
749 getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
751 StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
752 if (!Parallelism.empty()) {
753 CmdArgs.push_back("-mllvm");
754 unsigned NumThreads =
755 llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
756 CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
759 if (getToolChain().ShouldLinkCXXStdlib(Args))
760 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
762 bool NoStdOrDefaultLibs =
763 Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
764 bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
765 if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
766 // link_ssp spec is empty.
768 // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
769 // we just want to link the builtins, not the other libs like libSystem.
770 if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
771 getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");
772 } else {
773 // Let the tool chain choose which runtime library to link.
774 getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
775 ForceLinkBuiltins);
777 // No need to do anything for pthreads. Claim argument to avoid warning.
778 Args.ClaimAllArgs(options::OPT_pthread);
779 Args.ClaimAllArgs(options::OPT_pthreads);
783 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
784 // endfile_spec is empty.
787 Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
788 Args.AddAllArgs(CmdArgs, options::OPT_F);
790 // -iframework should be forwarded as -F.
791 for (const Arg *A : Args.filtered(options::OPT_iframework))
792 CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
794 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
795 if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
796 if (A->getValue() == StringRef("Accelerate")) {
797 CmdArgs.push_back("-framework");
798 CmdArgs.push_back("Accelerate");
803 // Add non-standard, platform-specific search paths, e.g., for DriverKit:
804 // -L<sysroot>/System/DriverKit/usr/lib
805 // -F<sysroot>/System/DriverKit/System/Library/Framework
807 bool NonStandardSearchPath = false;
808 const auto &Triple = getToolChain().getTriple();
809 if (Triple.isDriverKit()) {
810 // ld64 fixed the implicit -F and -L paths in ld64-605.1+.
811 NonStandardSearchPath =
812 Version.getMajor() < 605 ||
813 (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);
816 if (NonStandardSearchPath) {
817 if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
818 auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
819 SmallString<128> P(Sysroot->getValue());
820 AppendPlatformPrefix(P, Triple);
821 llvm::sys::path::append(P, SearchPath);
822 if (getToolChain().getVFS().exists(P)) {
823 CmdArgs.push_back(Args.MakeArgString(Flag + P));
826 AddSearchPath("-L", "/usr/lib");
827 AddSearchPath("-F", "/System/Library/Frameworks");
832 ResponseFileSupport ResponseSupport;
833 if (Version >= VersionTuple(705) || LinkerIsLLD) {
834 ResponseSupport = ResponseFileSupport::AtFileUTF8();
835 } else {
836 // For older versions of the linker, use the legacy filelist method instead.
837 ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
838 "-filelist"};
841 std::unique_ptr<Command> Cmd = std::make_unique<Command>(
842 JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
843 Cmd->setInputFileList(std::move(InputFileList));
844 C.addCommand(std::move(Cmd));
847 void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
848 const InputInfo &Output,
849 const InputInfoList &Inputs,
850 const ArgList &Args,
851 const char *LinkingOutput) const {
852 const Driver &D = getToolChain().getDriver();
854 // Silence warning for "clang -g foo.o -o foo"
855 Args.ClaimAllArgs(options::OPT_g_Group);
856 // and "clang -emit-llvm foo.o -o foo"
857 Args.ClaimAllArgs(options::OPT_emit_llvm);
858 // and for "clang -w foo.o -o foo". Other warning options are already
859 // handled somewhere else.
860 Args.ClaimAllArgs(options::OPT_w);
861 // Silence warnings when linking C code with a C++ '-stdlib' argument.
862 Args.ClaimAllArgs(options::OPT_stdlib_EQ);
864 // libtool <options> <output_file> <input_files>
865 ArgStringList CmdArgs;
866 // Create and insert file members with a deterministic index.
867 CmdArgs.push_back("-static");
868 CmdArgs.push_back("-D");
869 CmdArgs.push_back("-no_warning_for_no_symbols");
870 CmdArgs.push_back("-o");
871 CmdArgs.push_back(Output.getFilename());
873 for (const auto &II : Inputs) {
874 if (II.isFilename()) {
875 CmdArgs.push_back(II.getFilename());
879 // Delete old output archive file if it already exists before generating a new
880 // archive file.
881 const auto *OutputFileName = Output.getFilename();
882 if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
883 if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
884 D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
885 return;
889 const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
890 C.addCommand(std::make_unique<Command>(JA, *this,
891 ResponseFileSupport::AtFileUTF8(),
892 Exec, CmdArgs, Inputs, Output));
895 void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
896 const InputInfo &Output,
897 const InputInfoList &Inputs,
898 const ArgList &Args,
899 const char *LinkingOutput) const {
900 ArgStringList CmdArgs;
902 CmdArgs.push_back("-create");
903 assert(Output.isFilename() && "Unexpected lipo output.");
905 CmdArgs.push_back("-output");
906 CmdArgs.push_back(Output.getFilename());
908 for (const auto &II : Inputs) {
909 assert(II.isFilename() && "Unexpected lipo input.");
910 CmdArgs.push_back(II.getFilename());
913 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
914 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
915 Exec, CmdArgs, Inputs, Output));
918 void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
919 const InputInfo &Output,
920 const InputInfoList &Inputs,
921 const ArgList &Args,
922 const char *LinkingOutput) const {
923 ArgStringList CmdArgs;
925 CmdArgs.push_back("-o");
926 CmdArgs.push_back(Output.getFilename());
928 assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
929 const InputInfo &Input = Inputs[0];
930 assert(Input.isFilename() && "Unexpected dsymutil input.");
931 CmdArgs.push_back(Input.getFilename());
933 const char *Exec =
934 Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
935 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
936 Exec, CmdArgs, Inputs, Output));
939 void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
940 const InputInfo &Output,
941 const InputInfoList &Inputs,
942 const ArgList &Args,
943 const char *LinkingOutput) const {
944 ArgStringList CmdArgs;
945 CmdArgs.push_back("--verify");
946 CmdArgs.push_back("--debug-info");
947 CmdArgs.push_back("--eh-frame");
948 CmdArgs.push_back("--quiet");
950 assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
951 const InputInfo &Input = Inputs[0];
952 assert(Input.isFilename() && "Unexpected verify input");
954 // Grabbing the output of the earlier dsymutil run.
955 CmdArgs.push_back(Input.getFilename());
957 const char *Exec =
958 Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
959 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
960 Exec, CmdArgs, Inputs, Output));
963 MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
964 : ToolChain(D, Triple, Args) {
965 // We expect 'as', 'ld', etc. to be adjacent to our install dir.
966 getProgramPaths().push_back(getDriver().Dir);
969 /// Darwin - Darwin tool chain for i386 and x86_64.
970 Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
971 : MachO(D, Triple, Args), TargetInitialized(false),
972 CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
974 types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
975 types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
977 // Darwin always preprocesses assembly files (unless -x is used explicitly).
978 if (Ty == types::TY_PP_Asm)
979 return types::TY_Asm;
981 return Ty;
984 bool MachO::HasNativeLLVMSupport() const { return true; }
986 ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
987 // Always use libc++ by default
988 return ToolChain::CST_Libcxx;
991 /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
992 ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
993 if (isTargetWatchOSBased())
994 return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
995 if (isTargetIOSBased())
996 return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
997 if (isTargetXROS()) {
998 // XROS uses the iOS runtime.
999 auto T = llvm::Triple(Twine("arm64-apple-") +
1000 llvm::Triple::getOSTypeName(llvm::Triple::XROS) +
1001 TargetVersion.getAsString());
1002 return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion());
1004 if (isNonFragile)
1005 return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
1006 return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
1009 /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
1010 bool Darwin::hasBlocksRuntime() const {
1011 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())
1012 return true;
1013 else if (isTargetIOSBased())
1014 return !isIPhoneOSVersionLT(3, 2);
1015 else {
1016 assert(isTargetMacOSBased() && "unexpected darwin target");
1017 return !isMacosxVersionLT(10, 6);
1021 void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
1022 ArgStringList &CC1Args) const {
1023 CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
1026 void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
1027 ArgStringList &CC1Args) const {
1028 RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
1031 // This is just a MachO name translation routine and there's no
1032 // way to join this into ARMTargetParser without breaking all
1033 // other assumptions. Maybe MachO should consider standardising
1034 // their nomenclature.
1035 static const char *ArmMachOArchName(StringRef Arch) {
1036 return llvm::StringSwitch<const char *>(Arch)
1037 .Case("armv6k", "armv6")
1038 .Case("armv6m", "armv6m")
1039 .Case("armv5tej", "armv5")
1040 .Case("xscale", "xscale")
1041 .Case("armv4t", "armv4t")
1042 .Case("armv7", "armv7")
1043 .Cases("armv7a", "armv7-a", "armv7")
1044 .Cases("armv7r", "armv7-r", "armv7")
1045 .Cases("armv7em", "armv7e-m", "armv7em")
1046 .Cases("armv7k", "armv7-k", "armv7k")
1047 .Cases("armv7m", "armv7-m", "armv7m")
1048 .Cases("armv7s", "armv7-s", "armv7s")
1049 .Default(nullptr);
1052 static const char *ArmMachOArchNameCPU(StringRef CPU) {
1053 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
1054 if (ArchKind == llvm::ARM::ArchKind::INVALID)
1055 return nullptr;
1056 StringRef Arch = llvm::ARM::getArchName(ArchKind);
1058 // FIXME: Make sure this MachO triple mangling is really necessary.
1059 // ARMv5* normalises to ARMv5.
1060 if (Arch.starts_with("armv5"))
1061 Arch = Arch.substr(0, 5);
1062 // ARMv6*, except ARMv6M, normalises to ARMv6.
1063 else if (Arch.starts_with("armv6") && !Arch.ends_with("6m"))
1064 Arch = Arch.substr(0, 5);
1065 // ARMv7A normalises to ARMv7.
1066 else if (Arch.ends_with("v7a"))
1067 Arch = Arch.substr(0, 5);
1068 return Arch.data();
1071 StringRef MachO::getMachOArchName(const ArgList &Args) const {
1072 switch (getTriple().getArch()) {
1073 default:
1074 return getDefaultUniversalArchName();
1076 case llvm::Triple::aarch64_32:
1077 return "arm64_32";
1079 case llvm::Triple::aarch64: {
1080 if (getTriple().isArm64e())
1081 return "arm64e";
1082 return "arm64";
1085 case llvm::Triple::thumb:
1086 case llvm::Triple::arm:
1087 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
1088 if (const char *Arch = ArmMachOArchName(A->getValue()))
1089 return Arch;
1091 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
1092 if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
1093 return Arch;
1095 return "arm";
1099 VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
1100 if (LinkerVersion) {
1101 #ifndef NDEBUG
1102 VersionTuple NewLinkerVersion;
1103 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1104 (void)NewLinkerVersion.tryParse(A->getValue());
1105 assert(NewLinkerVersion == LinkerVersion);
1106 #endif
1107 return *LinkerVersion;
1110 VersionTuple NewLinkerVersion;
1111 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
1112 if (NewLinkerVersion.tryParse(A->getValue()))
1113 getDriver().Diag(diag::err_drv_invalid_version_number)
1114 << A->getAsString(Args);
1116 LinkerVersion = NewLinkerVersion;
1117 return *LinkerVersion;
1120 Darwin::~Darwin() {}
1122 MachO::~MachO() {}
1124 std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
1125 types::ID InputType) const {
1126 llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
1128 // If the target isn't initialized (e.g., an unknown Darwin platform, return
1129 // the default triple).
1130 if (!isTargetInitialized())
1131 return Triple.getTriple();
1133 SmallString<16> Str;
1134 if (isTargetWatchOSBased())
1135 Str += "watchos";
1136 else if (isTargetTvOSBased())
1137 Str += "tvos";
1138 else if (isTargetDriverKit())
1139 Str += "driverkit";
1140 else if (isTargetIOSBased() || isTargetMacCatalyst())
1141 Str += "ios";
1142 else if (isTargetXROS())
1143 Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS);
1144 else
1145 Str += "macosx";
1146 Str += getTripleTargetVersion().getAsString();
1147 Triple.setOSName(Str);
1149 return Triple.getTriple();
1152 Tool *MachO::getTool(Action::ActionClass AC) const {
1153 switch (AC) {
1154 case Action::LipoJobClass:
1155 if (!Lipo)
1156 Lipo.reset(new tools::darwin::Lipo(*this));
1157 return Lipo.get();
1158 case Action::DsymutilJobClass:
1159 if (!Dsymutil)
1160 Dsymutil.reset(new tools::darwin::Dsymutil(*this));
1161 return Dsymutil.get();
1162 case Action::VerifyDebugInfoJobClass:
1163 if (!VerifyDebug)
1164 VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
1165 return VerifyDebug.get();
1166 default:
1167 return ToolChain::getTool(AC);
1171 Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
1173 Tool *MachO::buildStaticLibTool() const {
1174 return new tools::darwin::StaticLibTool(*this);
1177 Tool *MachO::buildAssembler() const {
1178 return new tools::darwin::Assembler(*this);
1181 DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
1182 const ArgList &Args)
1183 : Darwin(D, Triple, Args) {}
1185 void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
1186 // Always error about undefined 'TARGET_OS_*' macros.
1187 CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
1188 CC1Args.push_back("-Werror=undef-prefix");
1190 // For modern targets, promote certain warnings to errors.
1191 if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
1192 // Always enable -Wdeprecated-objc-isa-usage and promote it
1193 // to an error.
1194 CC1Args.push_back("-Wdeprecated-objc-isa-usage");
1195 CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
1197 // For iOS and watchOS, also error about implicit function declarations,
1198 // as that can impact calling conventions.
1199 if (!isTargetMacOS())
1200 CC1Args.push_back("-Werror=implicit-function-declaration");
1204 /// Take a path that speculatively points into Xcode and return the
1205 /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path
1206 /// otherwise.
1207 static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
1208 static constexpr llvm::StringLiteral XcodeAppSuffix(
1209 ".app/Contents/Developer");
1210 size_t Index = PathIntoXcode.find(XcodeAppSuffix);
1211 if (Index == StringRef::npos)
1212 return "";
1213 return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());
1216 void DarwinClang::AddLinkARCArgs(const ArgList &Args,
1217 ArgStringList &CmdArgs) const {
1218 // Avoid linking compatibility stubs on i386 mac.
1219 if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)
1220 return;
1221 if (isTargetAppleSiliconMac())
1222 return;
1223 // ARC runtime is supported everywhere on arm64e.
1224 if (getTriple().isArm64e())
1225 return;
1226 if (isTargetXROS())
1227 return;
1229 ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
1231 if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
1232 runtime.hasSubscripting())
1233 return;
1235 SmallString<128> P(getDriver().ClangExecutable);
1236 llvm::sys::path::remove_filename(P); // 'clang'
1237 llvm::sys::path::remove_filename(P); // 'bin'
1238 llvm::sys::path::append(P, "lib", "arc");
1240 // 'libarclite' usually lives in the same toolchain as 'clang'. However, the
1241 // Swift open source toolchains for macOS distribute Clang without libarclite.
1242 // In that case, to allow the linker to find 'libarclite', we point to the
1243 // 'libarclite' in the XcodeDefault toolchain instead.
1244 if (!getVFS().exists(P)) {
1245 auto updatePath = [&](const Arg *A) {
1246 // Try to infer the path to 'libarclite' in the toolchain from the
1247 // specified SDK path.
1248 StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
1249 if (XcodePathForSDK.empty())
1250 return false;
1252 P = XcodePathForSDK;
1253 llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
1254 "lib", "arc");
1255 return getVFS().exists(P);
1258 bool updated = false;
1259 if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
1260 updated = updatePath(A);
1262 if (!updated) {
1263 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
1264 updatePath(A);
1268 CmdArgs.push_back("-force_load");
1269 llvm::sys::path::append(P, "libarclite_");
1270 // Mash in the platform.
1271 if (isTargetWatchOSSimulator())
1272 P += "watchsimulator";
1273 else if (isTargetWatchOS())
1274 P += "watchos";
1275 else if (isTargetTvOSSimulator())
1276 P += "appletvsimulator";
1277 else if (isTargetTvOS())
1278 P += "appletvos";
1279 else if (isTargetIOSSimulator())
1280 P += "iphonesimulator";
1281 else if (isTargetIPhoneOS())
1282 P += "iphoneos";
1283 else
1284 P += "macosx";
1285 P += ".a";
1287 if (!getVFS().exists(P))
1288 getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;
1290 CmdArgs.push_back(Args.MakeArgString(P));
1293 unsigned DarwinClang::GetDefaultDwarfVersion() const {
1294 // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
1295 if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
1296 (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
1297 return 2;
1298 // Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.
1299 if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||
1300 (isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||
1301 (isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||
1302 (isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||
1303 (isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||
1304 (isTargetMacOSBased() &&
1305 TargetVersion.empty())) // apple-darwin, no version.
1306 return 4;
1307 return 5;
1310 void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
1311 StringRef Component, RuntimeLinkOptions Opts,
1312 bool IsShared) const {
1313 std::string P = getCompilerRT(
1314 Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static);
1316 // For now, allow missing resource libraries to support developers who may
1317 // not have compiler-rt checked out or integrated into their build (unless
1318 // we explicitly force linking with this library).
1319 if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
1320 const char *LibArg = Args.MakeArgString(P);
1321 CmdArgs.push_back(LibArg);
1324 // Adding the rpaths might negatively interact when other rpaths are involved,
1325 // so we should make sure we add the rpaths last, after all user-specified
1326 // rpaths. This is currently true from this place, but we need to be
1327 // careful if this function is ever called before user's rpaths are emitted.
1328 if (Opts & RLO_AddRPath) {
1329 assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library");
1331 // Add @executable_path to rpath to support having the dylib copied with
1332 // the executable.
1333 CmdArgs.push_back("-rpath");
1334 CmdArgs.push_back("@executable_path");
1336 // Add the compiler-rt library's directory to rpath to support using the
1337 // dylib from the default location without copying.
1338 CmdArgs.push_back("-rpath");
1339 CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P)));
1343 std::string MachO::getCompilerRT(const ArgList &, StringRef Component,
1344 FileType Type) const {
1345 assert(Type != ToolChain::FT_Object &&
1346 "it doesn't make sense to ask for the compiler-rt library name as an "
1347 "object file");
1348 SmallString<64> MachOLibName = StringRef("libclang_rt");
1349 // On MachO, the builtins component is not in the library name
1350 if (Component != "builtins") {
1351 MachOLibName += '.';
1352 MachOLibName += Component;
1354 MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";
1356 SmallString<128> FullPath(getDriver().ResourceDir);
1357 llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded",
1358 MachOLibName);
1359 return std::string(FullPath);
1362 std::string Darwin::getCompilerRT(const ArgList &, StringRef Component,
1363 FileType Type) const {
1364 assert(Type != ToolChain::FT_Object &&
1365 "it doesn't make sense to ask for the compiler-rt library name as an "
1366 "object file");
1367 SmallString<64> DarwinLibName = StringRef("libclang_rt.");
1368 // On Darwin, the builtins component is not in the library name
1369 if (Component != "builtins") {
1370 DarwinLibName += Component;
1371 DarwinLibName += '_';
1373 DarwinLibName += getOSLibraryNameSuffix();
1374 DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";
1376 SmallString<128> FullPath(getDriver().ResourceDir);
1377 llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName);
1378 return std::string(FullPath);
1381 StringRef Darwin::getPlatformFamily() const {
1382 switch (TargetPlatform) {
1383 case DarwinPlatformKind::MacOS:
1384 return "MacOSX";
1385 case DarwinPlatformKind::IPhoneOS:
1386 if (TargetEnvironment == MacCatalyst)
1387 return "MacOSX";
1388 return "iPhone";
1389 case DarwinPlatformKind::TvOS:
1390 return "AppleTV";
1391 case DarwinPlatformKind::WatchOS:
1392 return "Watch";
1393 case DarwinPlatformKind::DriverKit:
1394 return "DriverKit";
1395 case DarwinPlatformKind::XROS:
1396 return "XR";
1398 llvm_unreachable("Unsupported platform");
1401 StringRef Darwin::getSDKName(StringRef isysroot) {
1402 // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
1403 auto BeginSDK = llvm::sys::path::rbegin(isysroot);
1404 auto EndSDK = llvm::sys::path::rend(isysroot);
1405 for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
1406 StringRef SDK = *IT;
1407 if (SDK.ends_with(".sdk"))
1408 return SDK.slice(0, SDK.size() - 4);
1410 return "";
1413 StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
1414 switch (TargetPlatform) {
1415 case DarwinPlatformKind::MacOS:
1416 return "osx";
1417 case DarwinPlatformKind::IPhoneOS:
1418 if (TargetEnvironment == MacCatalyst)
1419 return "osx";
1420 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
1421 : "iossim";
1422 case DarwinPlatformKind::TvOS:
1423 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
1424 : "tvossim";
1425 case DarwinPlatformKind::WatchOS:
1426 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
1427 : "watchossim";
1428 case DarwinPlatformKind::XROS:
1429 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros"
1430 : "xrossim";
1431 case DarwinPlatformKind::DriverKit:
1432 return "driverkit";
1434 llvm_unreachable("Unsupported platform");
1437 /// Check if the link command contains a symbol export directive.
1438 static bool hasExportSymbolDirective(const ArgList &Args) {
1439 for (Arg *A : Args) {
1440 if (A->getOption().matches(options::OPT_exported__symbols__list))
1441 return true;
1442 if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
1443 !A->getOption().matches(options::OPT_Xlinker))
1444 continue;
1445 if (A->containsValue("-exported_symbols_list") ||
1446 A->containsValue("-exported_symbol"))
1447 return true;
1449 return false;
1452 /// Add an export directive for \p Symbol to the link command.
1453 static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
1454 CmdArgs.push_back("-exported_symbol");
1455 CmdArgs.push_back(Symbol);
1458 /// Add a sectalign directive for \p Segment and \p Section to the maximum
1459 /// expected page size for Darwin.
1461 /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
1462 /// Use a common alignment constant (16K) for now, and reduce the alignment on
1463 /// macOS if it proves important.
1464 static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
1465 StringRef Segment, StringRef Section) {
1466 for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
1467 Args.MakeArgString(Section), "0x4000"})
1468 CmdArgs.push_back(A);
1471 void Darwin::addProfileRTLibs(const ArgList &Args,
1472 ArgStringList &CmdArgs) const {
1473 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1474 return;
1476 AddLinkRuntimeLib(Args, CmdArgs, "profile",
1477 RuntimeLinkOptions(RLO_AlwaysLink));
1479 bool ForGCOV = needsGCovInstrumentation(Args);
1481 // If we have a symbol export directive and we're linking in the profile
1482 // runtime, automatically export symbols necessary to implement some of the
1483 // runtime's functionality.
1484 if (hasExportSymbolDirective(Args) && ForGCOV) {
1485 addExportedSymbol(CmdArgs, "___gcov_dump");
1486 addExportedSymbol(CmdArgs, "___gcov_reset");
1487 addExportedSymbol(CmdArgs, "_writeout_fn_list");
1488 addExportedSymbol(CmdArgs, "_reset_fn_list");
1491 // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page
1492 // alignment. This allows profile counters to be mmap()'d to disk. Note that
1493 // it's not enough to just page-align __llvm_prf_cnts: the following section
1494 // must also be page-aligned so that its data is not clobbered by mmap().
1496 // The section alignment is only needed when continuous profile sync is
1497 // enabled, but this is expected to be the default in Xcode. Specifying the
1498 // extra alignment also allows the same binary to be used with/without sync
1499 // enabled.
1500 if (!ForGCOV) {
1501 for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {
1502 addSectalignToPage(
1503 Args, CmdArgs, "__DATA",
1504 llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
1505 /*AddSegmentInfo=*/false));
1510 void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
1511 ArgStringList &CmdArgs,
1512 StringRef Sanitizer,
1513 bool Shared) const {
1514 auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
1515 AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
1518 ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
1519 const ArgList &Args) const {
1520 if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
1521 StringRef Value = A->getValue();
1522 if (Value != "compiler-rt" && Value != "platform")
1523 getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
1524 << Value << "darwin";
1527 return ToolChain::RLT_CompilerRT;
1530 void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
1531 ArgStringList &CmdArgs,
1532 bool ForceLinkBuiltinRT) const {
1533 // Call once to ensure diagnostic is printed if wrong value was specified
1534 GetRuntimeLibType(Args);
1536 // Darwin doesn't support real static executables, don't link any runtime
1537 // libraries with -static.
1538 if (Args.hasArg(options::OPT_static) ||
1539 Args.hasArg(options::OPT_fapple_kext) ||
1540 Args.hasArg(options::OPT_mkernel)) {
1541 if (ForceLinkBuiltinRT)
1542 AddLinkRuntimeLib(Args, CmdArgs, "builtins");
1543 return;
1546 // Reject -static-libgcc for now, we can deal with this when and if someone
1547 // cares. This is useful in situations where someone wants to statically link
1548 // something like libstdc++, and needs its runtime support routines.
1549 if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
1550 getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
1551 return;
1554 const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
1556 if (!Sanitize.needsSharedRt()) {
1557 const char *sanitizer = nullptr;
1558 if (Sanitize.needsUbsanRt()) {
1559 sanitizer = "UndefinedBehaviorSanitizer";
1560 } else if (Sanitize.needsRtsanRt()) {
1561 sanitizer = "RealtimeSanitizer";
1562 } else if (Sanitize.needsAsanRt()) {
1563 sanitizer = "AddressSanitizer";
1564 } else if (Sanitize.needsTsanRt()) {
1565 sanitizer = "ThreadSanitizer";
1567 if (sanitizer) {
1568 getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)
1569 << sanitizer;
1570 return;
1574 if (Sanitize.linkRuntimes()) {
1575 if (Sanitize.needsAsanRt()) {
1576 if (Sanitize.needsStableAbi()) {
1577 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);
1578 } else {
1579 assert(Sanitize.needsSharedRt() &&
1580 "Static sanitizer runtimes not supported");
1581 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
1584 if (Sanitize.needsRtsanRt()) {
1585 assert(Sanitize.needsSharedRt() &&
1586 "Static sanitizer runtimes not supported");
1587 AddLinkSanitizerLibArgs(Args, CmdArgs, "rtsan");
1589 if (Sanitize.needsLsanRt())
1590 AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
1591 if (Sanitize.needsUbsanRt()) {
1592 assert(Sanitize.needsSharedRt() &&
1593 "Static sanitizer runtimes not supported");
1594 AddLinkSanitizerLibArgs(
1595 Args, CmdArgs,
1596 Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");
1598 if (Sanitize.needsTsanRt()) {
1599 assert(Sanitize.needsSharedRt() &&
1600 "Static sanitizer runtimes not supported");
1601 AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
1603 if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
1604 AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
1606 // Libfuzzer is written in C++ and requires libcxx.
1607 AddCXXStdlibLibArgs(Args, CmdArgs);
1609 if (Sanitize.needsStatsRt()) {
1610 AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
1611 AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
1615 const XRayArgs &XRay = getXRayArgs();
1616 if (XRay.needsXRayRt()) {
1617 AddLinkRuntimeLib(Args, CmdArgs, "xray");
1618 AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
1619 AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
1622 if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {
1623 CmdArgs.push_back("-framework");
1624 CmdArgs.push_back("DriverKit");
1627 // Otherwise link libSystem, then the dynamic runtime library, and finally any
1628 // target specific static runtime library.
1629 if (!isTargetDriverKit())
1630 CmdArgs.push_back("-lSystem");
1632 // Select the dynamic runtime library and the target specific static library.
1633 if (isTargetIOSBased()) {
1634 // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
1635 // it never went into the SDK.
1636 // Linking against libgcc_s.1 isn't needed for iOS 5.0+
1637 if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
1638 getTriple().getArch() != llvm::Triple::aarch64)
1639 CmdArgs.push_back("-lgcc_s.1");
1641 AddLinkRuntimeLib(Args, CmdArgs, "builtins");
1644 /// Returns the most appropriate macOS target version for the current process.
1646 /// If the macOS SDK version is the same or earlier than the system version,
1647 /// then the SDK version is returned. Otherwise the system version is returned.
1648 static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
1649 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
1650 if (!SystemTriple.isMacOSX())
1651 return std::string(MacOSSDKVersion);
1652 VersionTuple SystemVersion;
1653 SystemTriple.getMacOSXVersion(SystemVersion);
1655 unsigned Major, Minor, Micro;
1656 bool HadExtra;
1657 if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
1658 HadExtra))
1659 return std::string(MacOSSDKVersion);
1660 VersionTuple SDKVersion(Major, Minor, Micro);
1662 if (SDKVersion > SystemVersion)
1663 return SystemVersion.getAsString();
1664 return std::string(MacOSSDKVersion);
1667 namespace {
1669 /// The Darwin OS that was selected or inferred from arguments / environment.
1670 struct DarwinPlatform {
1671 enum SourceKind {
1672 /// The OS was specified using the -target argument.
1673 TargetArg,
1674 /// The OS was specified using the -mtargetos= argument.
1675 MTargetOSArg,
1676 /// The OS was specified using the -m<os>-version-min argument.
1677 OSVersionArg,
1678 /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
1679 DeploymentTargetEnv,
1680 /// The OS was inferred from the SDK.
1681 InferredFromSDK,
1682 /// The OS was inferred from the -arch.
1683 InferredFromArch
1686 using DarwinPlatformKind = Darwin::DarwinPlatformKind;
1687 using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;
1689 DarwinPlatformKind getPlatform() const { return Platform; }
1691 DarwinEnvironmentKind getEnvironment() const { return Environment; }
1693 void setEnvironment(DarwinEnvironmentKind Kind) {
1694 Environment = Kind;
1695 InferSimulatorFromArch = false;
1698 StringRef getOSVersion() const {
1699 if (Kind == OSVersionArg)
1700 return Argument->getValue();
1701 return OSVersion;
1704 void setOSVersion(StringRef S) {
1705 assert(Kind == TargetArg && "Unexpected kind!");
1706 OSVersion = std::string(S);
1709 bool hasOSVersion() const { return HasOSVersion; }
1711 VersionTuple getNativeTargetVersion() const {
1712 assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
1713 "native target version is specified only for Mac Catalyst");
1714 return NativeTargetVersion;
1717 /// Returns true if the target OS was explicitly specified.
1718 bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
1720 /// Returns true if the simulator environment can be inferred from the arch.
1721 bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
1723 const std::optional<llvm::Triple> &getTargetVariantTriple() const {
1724 return TargetVariantTriple;
1727 /// Adds the -m<os>-version-min argument to the compiler invocation.
1728 void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
1729 if (Argument)
1730 return;
1731 assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&
1732 "Invalid kind");
1733 options::ID Opt;
1734 switch (Platform) {
1735 case DarwinPlatformKind::MacOS:
1736 Opt = options::OPT_mmacos_version_min_EQ;
1737 break;
1738 case DarwinPlatformKind::IPhoneOS:
1739 Opt = options::OPT_mios_version_min_EQ;
1740 break;
1741 case DarwinPlatformKind::TvOS:
1742 Opt = options::OPT_mtvos_version_min_EQ;
1743 break;
1744 case DarwinPlatformKind::WatchOS:
1745 Opt = options::OPT_mwatchos_version_min_EQ;
1746 break;
1747 case DarwinPlatformKind::XROS:
1748 // xrOS always explicitly provides a version in the triple.
1749 return;
1750 case DarwinPlatformKind::DriverKit:
1751 // DriverKit always explicitly provides a version in the triple.
1752 return;
1754 Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
1755 Args.append(Argument);
1758 /// Returns the OS version with the argument / environment variable that
1759 /// specified it.
1760 std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
1761 switch (Kind) {
1762 case TargetArg:
1763 case MTargetOSArg:
1764 case OSVersionArg:
1765 case InferredFromSDK:
1766 case InferredFromArch:
1767 assert(Argument && "OS version argument not yet inferred");
1768 return Argument->getAsString(Args);
1769 case DeploymentTargetEnv:
1770 return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
1772 llvm_unreachable("Unsupported Darwin Source Kind");
1775 void setEnvironment(llvm::Triple::EnvironmentType EnvType,
1776 const VersionTuple &OSVersion,
1777 const std::optional<DarwinSDKInfo> &SDKInfo) {
1778 switch (EnvType) {
1779 case llvm::Triple::Simulator:
1780 Environment = DarwinEnvironmentKind::Simulator;
1781 break;
1782 case llvm::Triple::MacABI: {
1783 Environment = DarwinEnvironmentKind::MacCatalyst;
1784 // The minimum native macOS target for MacCatalyst is macOS 10.15.
1785 NativeTargetVersion = VersionTuple(10, 15);
1786 if (HasOSVersion && SDKInfo) {
1787 if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
1788 DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
1789 if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
1790 OSVersion, NativeTargetVersion, std::nullopt)) {
1791 NativeTargetVersion = *MacOSVersion;
1795 // In a zippered build, we could be building for a macOS target that's
1796 // lower than the version that's implied by the OS version. In that case
1797 // we need to use the minimum version as the native target version.
1798 if (TargetVariantTriple) {
1799 auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
1800 if (TargetVariantVersion.getMajor()) {
1801 if (TargetVariantVersion < NativeTargetVersion)
1802 NativeTargetVersion = TargetVariantVersion;
1805 break;
1807 default:
1808 break;
1812 static DarwinPlatform
1813 createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
1814 std::optional<llvm::Triple> TargetVariantTriple,
1815 const std::optional<DarwinSDKInfo> &SDKInfo) {
1816 DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
1818 VersionTuple OsVersion = TT.getOSVersion();
1819 if (OsVersion.getMajor() == 0)
1820 Result.HasOSVersion = false;
1821 Result.TargetVariantTriple = TargetVariantTriple;
1822 Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
1823 return Result;
1825 static DarwinPlatform
1826 createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
1827 llvm::Triple::EnvironmentType Environment, Arg *A,
1828 const std::optional<DarwinSDKInfo> &SDKInfo) {
1829 DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
1830 OSVersion.getAsString(), A);
1831 Result.InferSimulatorFromArch = false;
1832 Result.setEnvironment(Environment, OSVersion, SDKInfo);
1833 return Result;
1835 static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,
1836 bool IsSimulator) {
1837 DarwinPlatform Result{OSVersionArg, Platform, A};
1838 if (IsSimulator)
1839 Result.Environment = DarwinEnvironmentKind::Simulator;
1840 return Result;
1842 static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
1843 StringRef EnvVarName,
1844 StringRef Value) {
1845 DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
1846 Result.EnvVarName = EnvVarName;
1847 return Result;
1849 static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
1850 StringRef Value,
1851 bool IsSimulator = false) {
1852 DarwinPlatform Result(InferredFromSDK, Platform, Value);
1853 if (IsSimulator)
1854 Result.Environment = DarwinEnvironmentKind::Simulator;
1855 Result.InferSimulatorFromArch = false;
1856 return Result;
1858 static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
1859 StringRef Value) {
1860 return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
1863 /// Constructs an inferred SDKInfo value based on the version inferred from
1864 /// the SDK path itself. Only works for values that were created by inferring
1865 /// the platform from the SDKPath.
1866 DarwinSDKInfo inferSDKInfo() {
1867 assert(Kind == InferredFromSDK && "can infer SDK info only");
1868 llvm::VersionTuple Version;
1869 bool IsValid = !Version.tryParse(OSVersion);
1870 (void)IsValid;
1871 assert(IsValid && "invalid SDK version");
1872 return DarwinSDKInfo(
1873 Version,
1874 /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));
1877 private:
1878 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
1879 : Kind(Kind), Platform(Platform), Argument(Argument) {}
1880 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
1881 Arg *Argument = nullptr)
1882 : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
1884 static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
1885 switch (OS) {
1886 case llvm::Triple::Darwin:
1887 case llvm::Triple::MacOSX:
1888 return DarwinPlatformKind::MacOS;
1889 case llvm::Triple::IOS:
1890 return DarwinPlatformKind::IPhoneOS;
1891 case llvm::Triple::TvOS:
1892 return DarwinPlatformKind::TvOS;
1893 case llvm::Triple::WatchOS:
1894 return DarwinPlatformKind::WatchOS;
1895 case llvm::Triple::XROS:
1896 return DarwinPlatformKind::XROS;
1897 case llvm::Triple::DriverKit:
1898 return DarwinPlatformKind::DriverKit;
1899 default:
1900 llvm_unreachable("Unable to infer Darwin variant");
1904 SourceKind Kind;
1905 DarwinPlatformKind Platform;
1906 DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
1907 VersionTuple NativeTargetVersion;
1908 std::string OSVersion;
1909 bool HasOSVersion = true, InferSimulatorFromArch = true;
1910 Arg *Argument;
1911 StringRef EnvVarName;
1912 std::optional<llvm::Triple> TargetVariantTriple;
1915 /// Returns the deployment target that's specified using the -m<os>-version-min
1916 /// argument.
1917 std::optional<DarwinPlatform>
1918 getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
1919 const Driver &TheDriver) {
1920 Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
1921 Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
1922 options::OPT_mios_simulator_version_min_EQ);
1923 Arg *TvOSVersion =
1924 Args.getLastArg(options::OPT_mtvos_version_min_EQ,
1925 options::OPT_mtvos_simulator_version_min_EQ);
1926 Arg *WatchOSVersion =
1927 Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
1928 options::OPT_mwatchos_simulator_version_min_EQ);
1929 if (macOSVersion) {
1930 if (iOSVersion || TvOSVersion || WatchOSVersion) {
1931 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1932 << macOSVersion->getAsString(Args)
1933 << (iOSVersion ? iOSVersion
1934 : TvOSVersion ? TvOSVersion : WatchOSVersion)
1935 ->getAsString(Args);
1937 return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,
1938 /*IsSimulator=*/false);
1939 } else if (iOSVersion) {
1940 if (TvOSVersion || WatchOSVersion) {
1941 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1942 << iOSVersion->getAsString(Args)
1943 << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
1945 return DarwinPlatform::createOSVersionArg(
1946 Darwin::IPhoneOS, iOSVersion,
1947 iOSVersion->getOption().getID() ==
1948 options::OPT_mios_simulator_version_min_EQ);
1949 } else if (TvOSVersion) {
1950 if (WatchOSVersion) {
1951 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
1952 << TvOSVersion->getAsString(Args)
1953 << WatchOSVersion->getAsString(Args);
1955 return DarwinPlatform::createOSVersionArg(
1956 Darwin::TvOS, TvOSVersion,
1957 TvOSVersion->getOption().getID() ==
1958 options::OPT_mtvos_simulator_version_min_EQ);
1959 } else if (WatchOSVersion)
1960 return DarwinPlatform::createOSVersionArg(
1961 Darwin::WatchOS, WatchOSVersion,
1962 WatchOSVersion->getOption().getID() ==
1963 options::OPT_mwatchos_simulator_version_min_EQ);
1964 return std::nullopt;
1967 /// Returns the deployment target that's specified using the
1968 /// OS_DEPLOYMENT_TARGET environment variable.
1969 std::optional<DarwinPlatform>
1970 getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
1971 const llvm::Triple &Triple) {
1972 std::string Targets[Darwin::LastDarwinPlatform + 1];
1973 const char *EnvVars[] = {
1974 "MACOSX_DEPLOYMENT_TARGET",
1975 "IPHONEOS_DEPLOYMENT_TARGET",
1976 "TVOS_DEPLOYMENT_TARGET",
1977 "WATCHOS_DEPLOYMENT_TARGET",
1978 "DRIVERKIT_DEPLOYMENT_TARGET",
1979 "XROS_DEPLOYMENT_TARGET"
1981 static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,
1982 "Missing platform");
1983 for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {
1984 if (char *Env = ::getenv(I.value()))
1985 Targets[I.index()] = Env;
1988 // Allow conflicts among OSX and iOS for historical reasons, but choose the
1989 // default platform.
1990 if (!Targets[Darwin::MacOS].empty() &&
1991 (!Targets[Darwin::IPhoneOS].empty() ||
1992 !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() ||
1993 !Targets[Darwin::XROS].empty())) {
1994 if (Triple.getArch() == llvm::Triple::arm ||
1995 Triple.getArch() == llvm::Triple::aarch64 ||
1996 Triple.getArch() == llvm::Triple::thumb)
1997 Targets[Darwin::MacOS] = "";
1998 else
1999 Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
2000 Targets[Darwin::TvOS] = Targets[Darwin::XROS] = "";
2001 } else {
2002 // Don't allow conflicts in any other platform.
2003 unsigned FirstTarget = std::size(Targets);
2004 for (unsigned I = 0; I != std::size(Targets); ++I) {
2005 if (Targets[I].empty())
2006 continue;
2007 if (FirstTarget == std::size(Targets))
2008 FirstTarget = I;
2009 else
2010 TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
2011 << Targets[FirstTarget] << Targets[I];
2015 for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {
2016 if (!Target.value().empty())
2017 return DarwinPlatform::createDeploymentTargetEnv(
2018 (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
2019 Target.value());
2021 return std::nullopt;
2024 /// Returns the SDK name without the optional prefix that ends with a '.' or an
2025 /// empty string otherwise.
2026 static StringRef dropSDKNamePrefix(StringRef SDKName) {
2027 size_t PrefixPos = SDKName.find('.');
2028 if (PrefixPos == StringRef::npos)
2029 return "";
2030 return SDKName.substr(PrefixPos + 1);
2033 /// Tries to infer the deployment target from the SDK specified by -isysroot
2034 /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
2035 /// it's available.
2036 std::optional<DarwinPlatform>
2037 inferDeploymentTargetFromSDK(DerivedArgList &Args,
2038 const std::optional<DarwinSDKInfo> &SDKInfo) {
2039 const Arg *A = Args.getLastArg(options::OPT_isysroot);
2040 if (!A)
2041 return std::nullopt;
2042 StringRef isysroot = A->getValue();
2043 StringRef SDK = Darwin::getSDKName(isysroot);
2044 if (!SDK.size())
2045 return std::nullopt;
2047 std::string Version;
2048 if (SDKInfo) {
2049 // Get the version from the SDKSettings.json if it's available.
2050 Version = SDKInfo->getVersion().getAsString();
2051 } else {
2052 // Slice the version number out.
2053 // Version number is between the first and the last number.
2054 size_t StartVer = SDK.find_first_of("0123456789");
2055 size_t EndVer = SDK.find_last_of("0123456789");
2056 if (StartVer != StringRef::npos && EndVer > StartVer)
2057 Version = std::string(SDK.slice(StartVer, EndVer + 1));
2059 if (Version.empty())
2060 return std::nullopt;
2062 auto CreatePlatformFromSDKName =
2063 [&](StringRef SDK) -> std::optional<DarwinPlatform> {
2064 if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator"))
2065 return DarwinPlatform::createFromSDK(
2066 Darwin::IPhoneOS, Version,
2067 /*IsSimulator=*/SDK.starts_with("iPhoneSimulator"));
2068 else if (SDK.starts_with("MacOSX"))
2069 return DarwinPlatform::createFromSDK(Darwin::MacOS,
2070 getSystemOrSDKMacOSVersion(Version));
2071 else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator"))
2072 return DarwinPlatform::createFromSDK(
2073 Darwin::WatchOS, Version,
2074 /*IsSimulator=*/SDK.starts_with("WatchSimulator"));
2075 else if (SDK.starts_with("AppleTVOS") ||
2076 SDK.starts_with("AppleTVSimulator"))
2077 return DarwinPlatform::createFromSDK(
2078 Darwin::TvOS, Version,
2079 /*IsSimulator=*/SDK.starts_with("AppleTVSimulator"));
2080 else if (SDK.starts_with("XR"))
2081 return DarwinPlatform::createFromSDK(
2082 Darwin::XROS, Version,
2083 /*IsSimulator=*/SDK.contains("Simulator"));
2084 else if (SDK.starts_with("DriverKit"))
2085 return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);
2086 return std::nullopt;
2088 if (auto Result = CreatePlatformFromSDKName(SDK))
2089 return Result;
2090 // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
2091 return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
2094 std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
2095 const Driver &TheDriver) {
2096 VersionTuple OsVersion;
2097 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
2098 switch (OS) {
2099 case llvm::Triple::Darwin:
2100 case llvm::Triple::MacOSX:
2101 // If there is no version specified on triple, and both host and target are
2102 // macos, use the host triple to infer OS version.
2103 if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
2104 !Triple.getOSMajorVersion())
2105 SystemTriple.getMacOSXVersion(OsVersion);
2106 else if (!Triple.getMacOSXVersion(OsVersion))
2107 TheDriver.Diag(diag::err_drv_invalid_darwin_version)
2108 << Triple.getOSName();
2109 break;
2110 case llvm::Triple::IOS:
2111 if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
2112 OsVersion = VersionTuple(13, 1);
2113 } else
2114 OsVersion = Triple.getiOSVersion();
2115 break;
2116 case llvm::Triple::TvOS:
2117 OsVersion = Triple.getOSVersion();
2118 break;
2119 case llvm::Triple::WatchOS:
2120 OsVersion = Triple.getWatchOSVersion();
2121 break;
2122 case llvm::Triple::XROS:
2123 OsVersion = Triple.getOSVersion();
2124 if (!OsVersion.getMajor())
2125 OsVersion = OsVersion.withMajorReplaced(1);
2126 break;
2127 case llvm::Triple::DriverKit:
2128 OsVersion = Triple.getDriverKitVersion();
2129 break;
2130 default:
2131 llvm_unreachable("Unexpected OS type");
2132 break;
2135 std::string OSVersion;
2136 llvm::raw_string_ostream(OSVersion)
2137 << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
2138 << OsVersion.getSubminor().value_or(0);
2139 return OSVersion;
2142 /// Tries to infer the target OS from the -arch.
2143 std::optional<DarwinPlatform>
2144 inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
2145 const llvm::Triple &Triple,
2146 const Driver &TheDriver) {
2147 llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
2149 StringRef MachOArchName = Toolchain.getMachOArchName(Args);
2150 if (MachOArchName == "arm64" || MachOArchName == "arm64e")
2151 OSTy = llvm::Triple::MacOSX;
2152 else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
2153 OSTy = llvm::Triple::IOS;
2154 else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
2155 OSTy = llvm::Triple::WatchOS;
2156 else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
2157 MachOArchName != "armv7em")
2158 OSTy = llvm::Triple::MacOSX;
2159 if (OSTy == llvm::Triple::UnknownOS)
2160 return std::nullopt;
2161 return DarwinPlatform::createFromArch(OSTy,
2162 getOSVersion(OSTy, Triple, TheDriver));
2165 /// Returns the deployment target that's specified using the -target option.
2166 std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
2167 DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
2168 const std::optional<DarwinSDKInfo> &SDKInfo) {
2169 if (!Args.hasArg(options::OPT_target))
2170 return std::nullopt;
2171 if (Triple.getOS() == llvm::Triple::Darwin ||
2172 Triple.getOS() == llvm::Triple::UnknownOS)
2173 return std::nullopt;
2174 std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
2175 std::optional<llvm::Triple> TargetVariantTriple;
2176 for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
2177 llvm::Triple TVT(A->getValue());
2178 // Find a matching <arch>-<vendor> target variant triple that can be used.
2179 if ((Triple.getArch() == llvm::Triple::aarch64 ||
2180 TVT.getArchName() == Triple.getArchName()) &&
2181 TVT.getArch() == Triple.getArch() &&
2182 TVT.getSubArch() == Triple.getSubArch() &&
2183 TVT.getVendor() == Triple.getVendor()) {
2184 if (TargetVariantTriple)
2185 continue;
2186 A->claim();
2187 // Accept a -target-variant triple when compiling code that may run on
2188 // macOS or Mac Catalyst.
2189 if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
2190 TVT.isMacCatalystEnvironment()) ||
2191 (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
2192 Triple.isMacCatalystEnvironment())) {
2193 TargetVariantTriple = TVT;
2194 continue;
2196 TheDriver.Diag(diag::err_drv_target_variant_invalid)
2197 << A->getSpelling() << A->getValue();
2200 return DarwinPlatform::createFromTarget(Triple, OSVersion,
2201 Args.getLastArg(options::OPT_target),
2202 TargetVariantTriple, SDKInfo);
2205 /// Returns the deployment target that's specified using the -mtargetos option.
2206 std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
2207 DerivedArgList &Args, const Driver &TheDriver,
2208 const std::optional<DarwinSDKInfo> &SDKInfo) {
2209 auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
2210 if (!A)
2211 return std::nullopt;
2212 llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
2213 switch (TT.getOS()) {
2214 case llvm::Triple::MacOSX:
2215 case llvm::Triple::IOS:
2216 case llvm::Triple::TvOS:
2217 case llvm::Triple::WatchOS:
2218 case llvm::Triple::XROS:
2219 break;
2220 default:
2221 TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
2222 << TT.getOSName() << A->getAsString(Args);
2223 return std::nullopt;
2226 VersionTuple Version = TT.getOSVersion();
2227 if (!Version.getMajor()) {
2228 TheDriver.Diag(diag::err_drv_invalid_version_number)
2229 << A->getAsString(Args);
2230 return std::nullopt;
2232 return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,
2233 TT.getEnvironment(), A, SDKInfo);
2236 std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
2237 const ArgList &Args,
2238 const Driver &TheDriver) {
2239 const Arg *A = Args.getLastArg(options::OPT_isysroot);
2240 if (!A)
2241 return std::nullopt;
2242 StringRef isysroot = A->getValue();
2243 auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
2244 if (!SDKInfoOrErr) {
2245 llvm::consumeError(SDKInfoOrErr.takeError());
2246 TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
2247 return std::nullopt;
2249 return *SDKInfoOrErr;
2252 } // namespace
2254 void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
2255 const OptTable &Opts = getDriver().getOpts();
2257 // Support allowing the SDKROOT environment variable used by xcrun and other
2258 // Xcode tools to define the default sysroot, by making it the default for
2259 // isysroot.
2260 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2261 // Warn if the path does not exist.
2262 if (!getVFS().exists(A->getValue()))
2263 getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
2264 } else {
2265 if (char *env = ::getenv("SDKROOT")) {
2266 // We only use this value as the default if it is an absolute path,
2267 // exists, and it is not the root path.
2268 if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
2269 StringRef(env) != "/") {
2270 Args.append(Args.MakeSeparateArg(
2271 nullptr, Opts.getOption(options::OPT_isysroot), env));
2276 // Read the SDKSettings.json file for more information, like the SDK version
2277 // that we can pass down to the compiler.
2278 SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
2280 // The OS and the version can be specified using the -target argument.
2281 std::optional<DarwinPlatform> OSTarget =
2282 getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
2283 if (OSTarget) {
2284 // Disallow mixing -target and -mtargetos=.
2285 if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
2286 std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
2287 std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
2288 getDriver().Diag(diag::err_drv_cannot_mix_options)
2289 << TargetArgStr << MTargetOSArgStr;
2291 std::optional<DarwinPlatform> OSVersionArgTarget =
2292 getDeploymentTargetFromOSVersionArg(Args, getDriver());
2293 if (OSVersionArgTarget) {
2294 unsigned TargetMajor, TargetMinor, TargetMicro;
2295 bool TargetExtra;
2296 unsigned ArgMajor, ArgMinor, ArgMicro;
2297 bool ArgExtra;
2298 if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
2299 (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
2300 TargetMinor, TargetMicro, TargetExtra) &&
2301 Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
2302 ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
2303 (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
2304 VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
2305 TargetExtra != ArgExtra))) {
2306 // Select the OS version from the -m<os>-version-min argument when
2307 // the -target does not include an OS version.
2308 if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
2309 !OSTarget->hasOSVersion()) {
2310 OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
2311 } else {
2312 // Warn about -m<os>-version-min that doesn't match the OS version
2313 // that's specified in the target.
2314 std::string OSVersionArg =
2315 OSVersionArgTarget->getAsString(Args, Opts);
2316 std::string TargetArg = OSTarget->getAsString(Args, Opts);
2317 getDriver().Diag(clang::diag::warn_drv_overriding_option)
2318 << OSVersionArg << TargetArg;
2322 } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
2323 SDKInfo))) {
2324 // The OS target can be specified using the -mtargetos= argument.
2325 // Disallow mixing -mtargetos= and -m<os>version-min=.
2326 std::optional<DarwinPlatform> OSVersionArgTarget =
2327 getDeploymentTargetFromOSVersionArg(Args, getDriver());
2328 if (OSVersionArgTarget) {
2329 std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
2330 std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);
2331 getDriver().Diag(diag::err_drv_cannot_mix_options)
2332 << MTargetOSArgStr << OSVersionArgStr;
2334 } else {
2335 // The OS target can be specified using the -m<os>version-min argument.
2336 OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
2337 // If no deployment target was specified on the command line, check for
2338 // environment defines.
2339 if (!OSTarget) {
2340 OSTarget =
2341 getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
2342 if (OSTarget) {
2343 // Don't infer simulator from the arch when the SDK is also specified.
2344 std::optional<DarwinPlatform> SDKTarget =
2345 inferDeploymentTargetFromSDK(Args, SDKInfo);
2346 if (SDKTarget)
2347 OSTarget->setEnvironment(SDKTarget->getEnvironment());
2350 // If there is no command-line argument to specify the Target version and
2351 // no environment variable defined, see if we can set the default based
2352 // on -isysroot using SDKSettings.json if it exists.
2353 if (!OSTarget) {
2354 OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
2355 /// If the target was successfully constructed from the SDK path, try to
2356 /// infer the SDK info if the SDK doesn't have it.
2357 if (OSTarget && !SDKInfo)
2358 SDKInfo = OSTarget->inferSDKInfo();
2360 // If no OS targets have been specified, try to guess platform from -target
2361 // or arch name and compute the version from the triple.
2362 if (!OSTarget)
2363 OSTarget =
2364 inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
2367 assert(OSTarget && "Unable to infer Darwin variant");
2368 OSTarget->addOSVersionMinArgument(Args, Opts);
2369 DarwinPlatformKind Platform = OSTarget->getPlatform();
2371 unsigned Major, Minor, Micro;
2372 bool HadExtra;
2373 // The major version should not be over this number.
2374 const unsigned MajorVersionLimit = 1000;
2375 // Set the tool chain target information.
2376 if (Platform == MacOS) {
2377 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2378 Micro, HadExtra) ||
2379 HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
2380 Micro >= 100)
2381 getDriver().Diag(diag::err_drv_invalid_version_number)
2382 << OSTarget->getAsString(Args, Opts);
2383 } else if (Platform == IPhoneOS) {
2384 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2385 Micro, HadExtra) ||
2386 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2387 getDriver().Diag(diag::err_drv_invalid_version_number)
2388 << OSTarget->getAsString(Args, Opts);
2390 if (OSTarget->getEnvironment() == MacCatalyst &&
2391 (Major < 13 || (Major == 13 && Minor < 1))) {
2392 getDriver().Diag(diag::err_drv_invalid_version_number)
2393 << OSTarget->getAsString(Args, Opts);
2394 Major = 13;
2395 Minor = 1;
2396 Micro = 0;
2398 // For 32-bit targets, the deployment target for iOS has to be earlier than
2399 // iOS 11.
2400 if (getTriple().isArch32Bit() && Major >= 11) {
2401 // If the deployment target is explicitly specified, print a diagnostic.
2402 if (OSTarget->isExplicitlySpecified()) {
2403 if (OSTarget->getEnvironment() == MacCatalyst)
2404 getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
2405 else
2406 getDriver().Diag(diag::warn_invalid_ios_deployment_target)
2407 << OSTarget->getAsString(Args, Opts);
2408 // Otherwise, set it to 10.99.99.
2409 } else {
2410 Major = 10;
2411 Minor = 99;
2412 Micro = 99;
2415 } else if (Platform == TvOS) {
2416 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2417 Micro, HadExtra) ||
2418 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2419 getDriver().Diag(diag::err_drv_invalid_version_number)
2420 << OSTarget->getAsString(Args, Opts);
2421 } else if (Platform == WatchOS) {
2422 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2423 Micro, HadExtra) ||
2424 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
2425 getDriver().Diag(diag::err_drv_invalid_version_number)
2426 << OSTarget->getAsString(Args, Opts);
2427 } else if (Platform == DriverKit) {
2428 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2429 Micro, HadExtra) ||
2430 HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
2431 Micro >= 100)
2432 getDriver().Diag(diag::err_drv_invalid_version_number)
2433 << OSTarget->getAsString(Args, Opts);
2434 } else if (Platform == XROS) {
2435 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
2436 Micro, HadExtra) ||
2437 HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
2438 Micro >= 100)
2439 getDriver().Diag(diag::err_drv_invalid_version_number)
2440 << OSTarget->getAsString(Args, Opts);
2441 } else
2442 llvm_unreachable("unknown kind of Darwin platform");
2444 DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
2445 // Recognize iOS targets with an x86 architecture as the iOS simulator.
2446 if (Environment == NativeEnvironment && Platform != MacOS &&
2447 Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
2448 getTriple().isX86())
2449 Environment = Simulator;
2451 VersionTuple NativeTargetVersion;
2452 if (Environment == MacCatalyst)
2453 NativeTargetVersion = OSTarget->getNativeTargetVersion();
2454 setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
2455 TargetVariantTriple = OSTarget->getTargetVariantTriple();
2457 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2458 StringRef SDK = getSDKName(A->getValue());
2459 if (SDK.size() > 0) {
2460 size_t StartVer = SDK.find_first_of("0123456789");
2461 StringRef SDKName = SDK.slice(0, StartVer);
2462 if (!SDKName.starts_with(getPlatformFamily()) &&
2463 !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))
2464 getDriver().Diag(diag::warn_incompatible_sysroot)
2465 << SDKName << getPlatformFamily();
2470 // For certain platforms/environments almost all resources (e.g., headers) are
2471 // located in sub-directories, e.g., for DriverKit they live in
2472 // <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).
2473 static void AppendPlatformPrefix(SmallString<128> &Path,
2474 const llvm::Triple &T) {
2475 if (T.isDriverKit()) {
2476 llvm::sys::path::append(Path, "System", "DriverKit");
2480 // Returns the effective sysroot from either -isysroot or --sysroot, plus the
2481 // platform prefix (if any).
2482 llvm::SmallString<128>
2483 DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
2484 llvm::SmallString<128> Path("/");
2485 if (DriverArgs.hasArg(options::OPT_isysroot))
2486 Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
2487 else if (!getDriver().SysRoot.empty())
2488 Path = getDriver().SysRoot;
2490 if (hasEffectiveTriple()) {
2491 AppendPlatformPrefix(Path, getEffectiveTriple());
2493 return Path;
2496 void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2497 llvm::opt::ArgStringList &CC1Args) const {
2498 const Driver &D = getDriver();
2500 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2502 bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
2503 bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
2504 bool NoBuiltinInc = DriverArgs.hasFlag(
2505 options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
2506 bool ForceBuiltinInc = DriverArgs.hasFlag(
2507 options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
2509 // Add <sysroot>/usr/local/include
2510 if (!NoStdInc && !NoStdlibInc) {
2511 SmallString<128> P(Sysroot);
2512 llvm::sys::path::append(P, "usr", "local", "include");
2513 addSystemInclude(DriverArgs, CC1Args, P);
2516 // Add the Clang builtin headers (<resource>/include)
2517 if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
2518 SmallString<128> P(D.ResourceDir);
2519 llvm::sys::path::append(P, "include");
2520 addSystemInclude(DriverArgs, CC1Args, P);
2523 if (NoStdInc || NoStdlibInc)
2524 return;
2526 // Check for configure-time C include directories.
2527 llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
2528 if (!CIncludeDirs.empty()) {
2529 llvm::SmallVector<llvm::StringRef, 5> dirs;
2530 CIncludeDirs.split(dirs, ":");
2531 for (llvm::StringRef dir : dirs) {
2532 llvm::StringRef Prefix =
2533 llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
2534 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
2536 } else {
2537 // Otherwise, add <sysroot>/usr/include.
2538 SmallString<128> P(Sysroot);
2539 llvm::sys::path::append(P, "usr", "include");
2540 addExternCSystemInclude(DriverArgs, CC1Args, P.str());
2544 bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
2545 llvm::opt::ArgStringList &CC1Args,
2546 llvm::SmallString<128> Base,
2547 llvm::StringRef Version,
2548 llvm::StringRef ArchDir,
2549 llvm::StringRef BitDir) const {
2550 llvm::sys::path::append(Base, Version);
2552 // Add the base dir
2553 addSystemInclude(DriverArgs, CC1Args, Base);
2555 // Add the multilib dirs
2557 llvm::SmallString<128> P = Base;
2558 if (!ArchDir.empty())
2559 llvm::sys::path::append(P, ArchDir);
2560 if (!BitDir.empty())
2561 llvm::sys::path::append(P, BitDir);
2562 addSystemInclude(DriverArgs, CC1Args, P);
2565 // Add the backward dir
2567 llvm::SmallString<128> P = Base;
2568 llvm::sys::path::append(P, "backward");
2569 addSystemInclude(DriverArgs, CC1Args, P);
2572 return getVFS().exists(Base);
2575 void DarwinClang::AddClangCXXStdlibIncludeArgs(
2576 const llvm::opt::ArgList &DriverArgs,
2577 llvm::opt::ArgStringList &CC1Args) const {
2578 // The implementation from a base class will pass through the -stdlib to
2579 // CC1Args.
2580 // FIXME: this should not be necessary, remove usages in the frontend
2581 // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
2582 // Also check whether this is used for setting library search paths.
2583 ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
2585 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
2586 options::OPT_nostdincxx))
2587 return;
2589 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
2591 switch (GetCXXStdlibType(DriverArgs)) {
2592 case ToolChain::CST_Libcxx: {
2593 // On Darwin, libc++ can be installed in one of the following places:
2594 // 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
2595 // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
2597 // The precedence of paths is as listed above, i.e. we take the first path
2598 // that exists. Note that we never include libc++ twice -- we take the first
2599 // path that exists and don't send the other paths to CC1 (otherwise
2600 // include_next could break).
2602 // Check for (1)
2603 // Get from '<install>/bin' to '<install>/include/c++/v1'.
2604 // Note that InstallBin can be relative, so we use '..' instead of
2605 // parent_path.
2606 llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin
2607 llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
2608 if (getVFS().exists(InstallBin)) {
2609 addSystemInclude(DriverArgs, CC1Args, InstallBin);
2610 return;
2611 } else if (DriverArgs.hasArg(options::OPT_v)) {
2612 llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
2613 << "\"\n";
2616 // Otherwise, check for (2)
2617 llvm::SmallString<128> SysrootUsr = Sysroot;
2618 llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
2619 if (getVFS().exists(SysrootUsr)) {
2620 addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
2621 return;
2622 } else if (DriverArgs.hasArg(options::OPT_v)) {
2623 llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
2624 << "\"\n";
2627 // Otherwise, don't add any path.
2628 break;
2631 case ToolChain::CST_Libstdcxx:
2632 llvm::SmallString<128> UsrIncludeCxx = Sysroot;
2633 llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
2635 llvm::Triple::ArchType arch = getTriple().getArch();
2636 bool IsBaseFound = true;
2637 switch (arch) {
2638 default: break;
2640 case llvm::Triple::x86:
2641 case llvm::Triple::x86_64:
2642 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2643 "4.2.1",
2644 "i686-apple-darwin10",
2645 arch == llvm::Triple::x86_64 ? "x86_64" : "");
2646 IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2647 "4.0.0", "i686-apple-darwin8",
2648 "");
2649 break;
2651 case llvm::Triple::arm:
2652 case llvm::Triple::thumb:
2653 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2654 "4.2.1",
2655 "arm-apple-darwin10",
2656 "v7");
2657 IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2658 "4.2.1",
2659 "arm-apple-darwin10",
2660 "v6");
2661 break;
2663 case llvm::Triple::aarch64:
2664 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
2665 "4.2.1",
2666 "arm64-apple-darwin10",
2667 "");
2668 break;
2671 if (!IsBaseFound) {
2672 getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
2675 break;
2679 void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
2680 ArgStringList &CmdArgs) const {
2681 CXXStdlibType Type = GetCXXStdlibType(Args);
2683 switch (Type) {
2684 case ToolChain::CST_Libcxx:
2685 CmdArgs.push_back("-lc++");
2686 if (Args.hasArg(options::OPT_fexperimental_library))
2687 CmdArgs.push_back("-lc++experimental");
2688 break;
2690 case ToolChain::CST_Libstdcxx:
2691 // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
2692 // it was previously found in the gcc lib dir. However, for all the Darwin
2693 // platforms we care about it was -lstdc++.6, so we search for that
2694 // explicitly if we can't see an obvious -lstdc++ candidate.
2696 // Check in the sysroot first.
2697 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
2698 SmallString<128> P(A->getValue());
2699 llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
2701 if (!getVFS().exists(P)) {
2702 llvm::sys::path::remove_filename(P);
2703 llvm::sys::path::append(P, "libstdc++.6.dylib");
2704 if (getVFS().exists(P)) {
2705 CmdArgs.push_back(Args.MakeArgString(P));
2706 return;
2711 // Otherwise, look in the root.
2712 // FIXME: This should be removed someday when we don't have to care about
2713 // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
2714 if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
2715 getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
2716 CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
2717 return;
2720 // Otherwise, let the linker search.
2721 CmdArgs.push_back("-lstdc++");
2722 break;
2726 void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
2727 ArgStringList &CmdArgs) const {
2728 // For Darwin platforms, use the compiler-rt-based support library
2729 // instead of the gcc-provided one (which is also incidentally
2730 // only present in the gcc lib dir, which makes it hard to find).
2732 SmallString<128> P(getDriver().ResourceDir);
2733 llvm::sys::path::append(P, "lib", "darwin");
2735 // Use the newer cc_kext for iOS ARM after 6.0.
2736 if (isTargetWatchOS()) {
2737 llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
2738 } else if (isTargetTvOS()) {
2739 llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
2740 } else if (isTargetIPhoneOS()) {
2741 llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
2742 } else if (isTargetDriverKit()) {
2743 // DriverKit doesn't want extra runtime support.
2744 } else if (isTargetXROSDevice()) {
2745 llvm::sys::path::append(
2746 P, llvm::Twine("libclang_rt.cc_kext_") +
2747 llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a");
2748 } else {
2749 llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
2752 // For now, allow missing resource libraries to support developers who may
2753 // not have compiler-rt checked out or integrated into their build.
2754 if (getVFS().exists(P))
2755 CmdArgs.push_back(Args.MakeArgString(P));
2758 DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
2759 StringRef BoundArch,
2760 Action::OffloadKind) const {
2761 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
2762 const OptTable &Opts = getDriver().getOpts();
2764 // FIXME: We really want to get out of the tool chain level argument
2765 // translation business, as it makes the driver functionality much
2766 // more opaque. For now, we follow gcc closely solely for the
2767 // purpose of easily achieving feature parity & testability. Once we
2768 // have something that works, we should reevaluate each translation
2769 // and try to push it down into tool specific logic.
2771 for (Arg *A : Args) {
2772 if (A->getOption().matches(options::OPT_Xarch__)) {
2773 // Skip this argument unless the architecture matches either the toolchain
2774 // triple arch, or the arch being bound.
2775 StringRef XarchArch = A->getValue(0);
2776 if (!(XarchArch == getArchName() ||
2777 (!BoundArch.empty() && XarchArch == BoundArch)))
2778 continue;
2780 Arg *OriginalArg = A;
2781 TranslateXarchArgs(Args, A, DAL);
2783 // Linker input arguments require custom handling. The problem is that we
2784 // have already constructed the phase actions, so we can not treat them as
2785 // "input arguments".
2786 if (A->getOption().hasFlag(options::LinkerInput)) {
2787 // Convert the argument into individual Zlinker_input_args.
2788 for (const char *Value : A->getValues()) {
2789 DAL->AddSeparateArg(
2790 OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
2792 continue;
2796 // Sob. These is strictly gcc compatible for the time being. Apple
2797 // gcc translates options twice, which means that self-expanding
2798 // options add duplicates.
2799 switch ((options::ID)A->getOption().getID()) {
2800 default:
2801 DAL->append(A);
2802 break;
2804 case options::OPT_mkernel:
2805 case options::OPT_fapple_kext:
2806 DAL->append(A);
2807 DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
2808 break;
2810 case options::OPT_dependency_file:
2811 DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
2812 break;
2814 case options::OPT_gfull:
2815 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2816 DAL->AddFlagArg(
2817 A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
2818 break;
2820 case options::OPT_gused:
2821 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
2822 DAL->AddFlagArg(
2823 A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
2824 break;
2826 case options::OPT_shared:
2827 DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
2828 break;
2830 case options::OPT_fconstant_cfstrings:
2831 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
2832 break;
2834 case options::OPT_fno_constant_cfstrings:
2835 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
2836 break;
2838 case options::OPT_Wnonportable_cfstrings:
2839 DAL->AddFlagArg(A,
2840 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
2841 break;
2843 case options::OPT_Wno_nonportable_cfstrings:
2844 DAL->AddFlagArg(
2845 A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
2846 break;
2850 // Add the arch options based on the particular spelling of -arch, to match
2851 // how the driver works.
2852 if (!BoundArch.empty()) {
2853 StringRef Name = BoundArch;
2854 const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
2855 const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);
2857 // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
2858 // which defines the list of which architectures we accept.
2859 if (Name == "ppc")
2861 else if (Name == "ppc601")
2862 DAL->AddJoinedArg(nullptr, MCpu, "601");
2863 else if (Name == "ppc603")
2864 DAL->AddJoinedArg(nullptr, MCpu, "603");
2865 else if (Name == "ppc604")
2866 DAL->AddJoinedArg(nullptr, MCpu, "604");
2867 else if (Name == "ppc604e")
2868 DAL->AddJoinedArg(nullptr, MCpu, "604e");
2869 else if (Name == "ppc750")
2870 DAL->AddJoinedArg(nullptr, MCpu, "750");
2871 else if (Name == "ppc7400")
2872 DAL->AddJoinedArg(nullptr, MCpu, "7400");
2873 else if (Name == "ppc7450")
2874 DAL->AddJoinedArg(nullptr, MCpu, "7450");
2875 else if (Name == "ppc970")
2876 DAL->AddJoinedArg(nullptr, MCpu, "970");
2878 else if (Name == "ppc64" || Name == "ppc64le")
2879 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2881 else if (Name == "i386")
2883 else if (Name == "i486")
2884 DAL->AddJoinedArg(nullptr, MArch, "i486");
2885 else if (Name == "i586")
2886 DAL->AddJoinedArg(nullptr, MArch, "i586");
2887 else if (Name == "i686")
2888 DAL->AddJoinedArg(nullptr, MArch, "i686");
2889 else if (Name == "pentium")
2890 DAL->AddJoinedArg(nullptr, MArch, "pentium");
2891 else if (Name == "pentium2")
2892 DAL->AddJoinedArg(nullptr, MArch, "pentium2");
2893 else if (Name == "pentpro")
2894 DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
2895 else if (Name == "pentIIm3")
2896 DAL->AddJoinedArg(nullptr, MArch, "pentium2");
2898 else if (Name == "x86_64" || Name == "x86_64h")
2899 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
2901 else if (Name == "arm")
2902 DAL->AddJoinedArg(nullptr, MArch, "armv4t");
2903 else if (Name == "armv4t")
2904 DAL->AddJoinedArg(nullptr, MArch, "armv4t");
2905 else if (Name == "armv5")
2906 DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
2907 else if (Name == "xscale")
2908 DAL->AddJoinedArg(nullptr, MArch, "xscale");
2909 else if (Name == "armv6")
2910 DAL->AddJoinedArg(nullptr, MArch, "armv6k");
2911 else if (Name == "armv6m")
2912 DAL->AddJoinedArg(nullptr, MArch, "armv6m");
2913 else if (Name == "armv7")
2914 DAL->AddJoinedArg(nullptr, MArch, "armv7a");
2915 else if (Name == "armv7em")
2916 DAL->AddJoinedArg(nullptr, MArch, "armv7em");
2917 else if (Name == "armv7k")
2918 DAL->AddJoinedArg(nullptr, MArch, "armv7k");
2919 else if (Name == "armv7m")
2920 DAL->AddJoinedArg(nullptr, MArch, "armv7m");
2921 else if (Name == "armv7s")
2922 DAL->AddJoinedArg(nullptr, MArch, "armv7s");
2925 return DAL;
2928 void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
2929 ArgStringList &CmdArgs,
2930 bool ForceLinkBuiltinRT) const {
2931 // Embedded targets are simple at the moment, not supporting sanitizers and
2932 // with different libraries for each member of the product { static, PIC } x
2933 // { hard-float, soft-float }
2934 llvm::SmallString<32> CompilerRT = StringRef("");
2935 CompilerRT +=
2936 (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
2937 ? "hard"
2938 : "soft";
2939 CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
2941 AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
2944 bool Darwin::isAlignedAllocationUnavailable() const {
2945 llvm::Triple::OSType OS;
2947 if (isTargetMacCatalyst())
2948 return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);
2949 switch (TargetPlatform) {
2950 case MacOS: // Earlier than 10.13.
2951 OS = llvm::Triple::MacOSX;
2952 break;
2953 case IPhoneOS:
2954 OS = llvm::Triple::IOS;
2955 break;
2956 case TvOS: // Earlier than 11.0.
2957 OS = llvm::Triple::TvOS;
2958 break;
2959 case WatchOS: // Earlier than 4.0.
2960 OS = llvm::Triple::WatchOS;
2961 break;
2962 case XROS: // Always available.
2963 return false;
2964 case DriverKit: // Always available.
2965 return false;
2968 return TargetVersion < alignedAllocMinVersion(OS);
2971 static bool sdkSupportsBuiltinModules(
2972 const Darwin::DarwinPlatformKind &TargetPlatform,
2973 const Darwin::DarwinEnvironmentKind &TargetEnvironment,
2974 const std::optional<DarwinSDKInfo> &SDKInfo) {
2975 if (TargetEnvironment == Darwin::NativeEnvironment ||
2976 TargetEnvironment == Darwin::Simulator ||
2977 TargetEnvironment == Darwin::MacCatalyst) {
2978 // Standard xnu/Mach/Darwin based environments
2979 // depend on the SDK version.
2980 } else {
2981 // All other environments support builtin modules from the start.
2982 return true;
2985 if (!SDKInfo)
2986 // If there is no SDK info, assume this is building against a
2987 // pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those
2988 // don't support modules anyway, but the headers definitely
2989 // don't support builtin modules either. It might also be some
2990 // kind of degenerate build environment, err on the side of
2991 // the old behavior which is to not use builtin modules.
2992 return false;
2994 VersionTuple SDKVersion = SDKInfo->getVersion();
2995 switch (TargetPlatform) {
2996 // Existing SDKs added support for builtin modules in the fall
2997 // 2024 major releases.
2998 case Darwin::MacOS:
2999 return SDKVersion >= VersionTuple(15U);
3000 case Darwin::IPhoneOS:
3001 switch (TargetEnvironment) {
3002 case Darwin::MacCatalyst:
3003 // Mac Catalyst uses `-target arm64-apple-ios18.0-macabi` so the platform
3004 // is iOS, but it builds with the macOS SDK, so it's the macOS SDK version
3005 // that's relevant.
3006 return SDKVersion >= VersionTuple(15U);
3007 default:
3008 return SDKVersion >= VersionTuple(18U);
3010 case Darwin::TvOS:
3011 return SDKVersion >= VersionTuple(18U);
3012 case Darwin::WatchOS:
3013 return SDKVersion >= VersionTuple(11U);
3014 case Darwin::XROS:
3015 return SDKVersion >= VersionTuple(2U);
3017 // New SDKs support builtin modules from the start.
3018 default:
3019 return true;
3023 static inline llvm::VersionTuple
3024 sizedDeallocMinVersion(llvm::Triple::OSType OS) {
3025 switch (OS) {
3026 default:
3027 break;
3028 case llvm::Triple::Darwin:
3029 case llvm::Triple::MacOSX: // Earliest supporting version is 10.12.
3030 return llvm::VersionTuple(10U, 12U);
3031 case llvm::Triple::IOS:
3032 case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0.
3033 return llvm::VersionTuple(10U);
3034 case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0.
3035 return llvm::VersionTuple(3U);
3038 llvm_unreachable("Unexpected OS");
3041 bool Darwin::isSizedDeallocationUnavailable() const {
3042 llvm::Triple::OSType OS;
3044 if (isTargetMacCatalyst())
3045 return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX);
3046 switch (TargetPlatform) {
3047 case MacOS: // Earlier than 10.12.
3048 OS = llvm::Triple::MacOSX;
3049 break;
3050 case IPhoneOS:
3051 OS = llvm::Triple::IOS;
3052 break;
3053 case TvOS: // Earlier than 10.0.
3054 OS = llvm::Triple::TvOS;
3055 break;
3056 case WatchOS: // Earlier than 3.0.
3057 OS = llvm::Triple::WatchOS;
3058 break;
3059 case DriverKit:
3060 case XROS:
3061 // Always available.
3062 return false;
3065 return TargetVersion < sizedDeallocMinVersion(OS);
3068 void Darwin::addClangTargetOptions(
3069 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
3070 Action::OffloadKind DeviceOffloadKind) const {
3071 // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
3072 // enabled or disabled aligned allocations.
3073 if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
3074 options::OPT_fno_aligned_allocation) &&
3075 isAlignedAllocationUnavailable())
3076 CC1Args.push_back("-faligned-alloc-unavailable");
3078 // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled
3079 // or disabled sized deallocations.
3080 if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,
3081 options::OPT_fno_sized_deallocation) &&
3082 isSizedDeallocationUnavailable())
3083 CC1Args.push_back("-fno-sized-deallocation");
3085 addClangCC1ASTargetOptions(DriverArgs, CC1Args);
3087 // Enable compatibility mode for NSItemProviderCompletionHandler in
3088 // Foundation/NSItemProvider.h.
3089 CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
3091 // Give static local variables in inline functions hidden visibility when
3092 // -fvisibility-inlines-hidden is enabled.
3093 if (!DriverArgs.getLastArgNoClaim(
3094 options::OPT_fvisibility_inlines_hidden_static_local_var,
3095 options::OPT_fno_visibility_inlines_hidden_static_local_var))
3096 CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
3098 // Earlier versions of the darwin SDK have the C standard library headers
3099 // all together in the Darwin module. That leads to module cycles with
3100 // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
3101 // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
3102 // darwin headers are in the Darwin module, there's a module cycle Darwin ->
3103 // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
3104 // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
3105 // but until then, the builtin headers need to join the system modules.
3106 // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
3107 // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
3108 // to fix the same problem with C++ headers, and is generally fragile.
3109 if (!sdkSupportsBuiltinModules(TargetPlatform, TargetEnvironment, SDKInfo))
3110 CC1Args.push_back("-fbuiltin-headers-in-system-modules");
3112 if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,
3113 options::OPT_fno_define_target_os_macros))
3114 CC1Args.push_back("-fdefine-target-os-macros");
3116 // Disable subdirectory modulemap search on sufficiently recent SDKs.
3117 if (SDKInfo &&
3118 !DriverArgs.hasFlag(options::OPT_fmodulemap_allow_subdirectory_search,
3119 options::OPT_fno_modulemap_allow_subdirectory_search,
3120 false)) {
3121 bool RequiresSubdirectorySearch;
3122 VersionTuple SDKVersion = SDKInfo->getVersion();
3123 switch (TargetPlatform) {
3124 default:
3125 RequiresSubdirectorySearch = true;
3126 break;
3127 case MacOS:
3128 RequiresSubdirectorySearch = SDKVersion < VersionTuple(15, 0);
3129 break;
3130 case IPhoneOS:
3131 case TvOS:
3132 RequiresSubdirectorySearch = SDKVersion < VersionTuple(18, 0);
3133 break;
3134 case WatchOS:
3135 RequiresSubdirectorySearch = SDKVersion < VersionTuple(11, 0);
3136 break;
3137 case XROS:
3138 RequiresSubdirectorySearch = SDKVersion < VersionTuple(2, 0);
3139 break;
3141 if (!RequiresSubdirectorySearch)
3142 CC1Args.push_back("-fno-modulemap-allow-subdirectory-search");
3146 void Darwin::addClangCC1ASTargetOptions(
3147 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
3148 if (TargetVariantTriple) {
3149 CC1ASArgs.push_back("-darwin-target-variant-triple");
3150 CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));
3153 if (SDKInfo) {
3154 /// Pass the SDK version to the compiler when the SDK information is
3155 /// available.
3156 auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
3157 std::string Arg;
3158 llvm::raw_string_ostream OS(Arg);
3159 OS << "-target-sdk-version=" << V;
3160 CC1ASArgs.push_back(Args.MakeArgString(Arg));
3163 if (isTargetMacCatalyst()) {
3164 if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
3165 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3166 std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
3167 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
3168 std::nullopt);
3169 EmitTargetSDKVersionArg(
3170 SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
3172 } else {
3173 EmitTargetSDKVersionArg(SDKInfo->getVersion());
3176 /// Pass the target variant SDK version to the compiler when the SDK
3177 /// information is available and is required for target variant.
3178 if (TargetVariantTriple) {
3179 if (isTargetMacCatalyst()) {
3180 std::string Arg;
3181 llvm::raw_string_ostream OS(Arg);
3182 OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
3183 CC1ASArgs.push_back(Args.MakeArgString(Arg));
3184 } else if (const auto *MacOStoMacCatalystMapping =
3185 SDKInfo->getVersionMapping(
3186 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3187 if (std::optional<VersionTuple> SDKVersion =
3188 MacOStoMacCatalystMapping->map(
3189 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
3190 std::nullopt)) {
3191 std::string Arg;
3192 llvm::raw_string_ostream OS(Arg);
3193 OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
3194 CC1ASArgs.push_back(Args.MakeArgString(Arg));
3201 DerivedArgList *
3202 Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
3203 Action::OffloadKind DeviceOffloadKind) const {
3204 // First get the generic Apple args, before moving onto Darwin-specific ones.
3205 DerivedArgList *DAL =
3206 MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
3208 // If no architecture is bound, none of the translations here are relevant.
3209 if (BoundArch.empty())
3210 return DAL;
3212 // Add an explicit version min argument for the deployment target. We do this
3213 // after argument translation because -Xarch_ arguments may add a version min
3214 // argument.
3215 AddDeploymentTarget(*DAL);
3217 // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
3218 // FIXME: It would be far better to avoid inserting those -static arguments,
3219 // but we can't check the deployment target in the translation code until
3220 // it is set here.
3221 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||
3222 (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
3223 for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
3224 Arg *A = *it;
3225 ++it;
3226 if (A->getOption().getID() != options::OPT_mkernel &&
3227 A->getOption().getID() != options::OPT_fapple_kext)
3228 continue;
3229 assert(it != ie && "unexpected argument translation");
3230 A = *it;
3231 assert(A->getOption().getID() == options::OPT_static &&
3232 "missing expected -static argument");
3233 *it = nullptr;
3234 ++it;
3238 auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
3239 if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
3240 if (Args.hasFlag(options::OPT_fomit_frame_pointer,
3241 options::OPT_fno_omit_frame_pointer, false))
3242 getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
3243 << "-fomit-frame-pointer" << BoundArch;
3246 return DAL;
3249 ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
3250 // Unwind tables are not emitted if -fno-exceptions is supplied (except when
3251 // targeting x86_64).
3252 if (getArch() == llvm::Triple::x86_64 ||
3253 (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
3254 Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
3255 true)))
3256 return (getArch() == llvm::Triple::aarch64 ||
3257 getArch() == llvm::Triple::aarch64_32)
3258 ? UnwindTableLevel::Synchronous
3259 : UnwindTableLevel::Asynchronous;
3261 return UnwindTableLevel::None;
3264 bool MachO::UseDwarfDebugFlags() const {
3265 if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
3266 return S[0] != '\0';
3267 return false;
3270 std::string MachO::GetGlobalDebugPathRemapping() const {
3271 if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))
3272 return S;
3273 return {};
3276 llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
3277 // Darwin uses SjLj exceptions on ARM.
3278 if (getTriple().getArch() != llvm::Triple::arm &&
3279 getTriple().getArch() != llvm::Triple::thumb)
3280 return llvm::ExceptionHandling::None;
3282 // Only watchOS uses the new DWARF/Compact unwinding method.
3283 llvm::Triple Triple(ComputeLLVMTriple(Args));
3284 if (Triple.isWatchABI())
3285 return llvm::ExceptionHandling::DwarfCFI;
3287 return llvm::ExceptionHandling::SjLj;
3290 bool Darwin::SupportsEmbeddedBitcode() const {
3291 assert(TargetInitialized && "Target not initialized!");
3292 if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
3293 return false;
3294 return true;
3297 bool MachO::isPICDefault() const { return true; }
3299 bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
3301 bool MachO::isPICDefaultForced() const {
3302 return (getArch() == llvm::Triple::x86_64 ||
3303 getArch() == llvm::Triple::aarch64);
3306 bool MachO::SupportsProfiling() const {
3307 // Profiling instrumentation is only supported on x86.
3308 return getTriple().isX86();
3311 void Darwin::addMinVersionArgs(const ArgList &Args,
3312 ArgStringList &CmdArgs) const {
3313 VersionTuple TargetVersion = getTripleTargetVersion();
3315 assert(!isTargetXROS() && "xrOS always uses -platform-version");
3317 if (isTargetWatchOS())
3318 CmdArgs.push_back("-watchos_version_min");
3319 else if (isTargetWatchOSSimulator())
3320 CmdArgs.push_back("-watchos_simulator_version_min");
3321 else if (isTargetTvOS())
3322 CmdArgs.push_back("-tvos_version_min");
3323 else if (isTargetTvOSSimulator())
3324 CmdArgs.push_back("-tvos_simulator_version_min");
3325 else if (isTargetDriverKit())
3326 CmdArgs.push_back("-driverkit_version_min");
3327 else if (isTargetIOSSimulator())
3328 CmdArgs.push_back("-ios_simulator_version_min");
3329 else if (isTargetIOSBased())
3330 CmdArgs.push_back("-iphoneos_version_min");
3331 else if (isTargetMacCatalyst())
3332 CmdArgs.push_back("-maccatalyst_version_min");
3333 else {
3334 assert(isTargetMacOS() && "unexpected target");
3335 CmdArgs.push_back("-macosx_version_min");
3338 VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
3339 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3340 TargetVersion = MinTgtVers;
3341 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3342 if (TargetVariantTriple) {
3343 assert(isTargetMacOSBased() && "unexpected target");
3344 VersionTuple VariantTargetVersion;
3345 if (TargetVariantTriple->isMacOSX()) {
3346 CmdArgs.push_back("-macosx_version_min");
3347 TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);
3348 } else {
3349 assert(TargetVariantTriple->isiOS() &&
3350 TargetVariantTriple->isMacCatalystEnvironment() &&
3351 "unexpected target variant triple");
3352 CmdArgs.push_back("-maccatalyst_version_min");
3353 VariantTargetVersion = TargetVariantTriple->getiOSVersion();
3355 VersionTuple MinTgtVers =
3356 TargetVariantTriple->getMinimumSupportedOSVersion();
3357 if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
3358 VariantTargetVersion = MinTgtVers;
3359 CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));
3363 static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
3364 Darwin::DarwinEnvironmentKind Environment) {
3365 switch (Platform) {
3366 case Darwin::MacOS:
3367 return "macos";
3368 case Darwin::IPhoneOS:
3369 if (Environment == Darwin::MacCatalyst)
3370 return "mac catalyst";
3371 return "ios";
3372 case Darwin::TvOS:
3373 return "tvos";
3374 case Darwin::WatchOS:
3375 return "watchos";
3376 case Darwin::XROS:
3377 return "xros";
3378 case Darwin::DriverKit:
3379 return "driverkit";
3381 llvm_unreachable("invalid platform");
3384 void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
3385 llvm::opt::ArgStringList &CmdArgs) const {
3386 auto EmitPlatformVersionArg =
3387 [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
3388 Darwin::DarwinEnvironmentKind TargetEnvironment,
3389 const llvm::Triple &TT) {
3390 // -platform_version <platform> <target_version> <sdk_version>
3391 // Both the target and SDK version support only up to 3 components.
3392 CmdArgs.push_back("-platform_version");
3393 std::string PlatformName =
3394 getPlatformName(TargetPlatform, TargetEnvironment);
3395 if (TargetEnvironment == Darwin::Simulator)
3396 PlatformName += "-simulator";
3397 CmdArgs.push_back(Args.MakeArgString(PlatformName));
3398 VersionTuple TargetVersion = TV.withoutBuild();
3399 if ((TargetPlatform == Darwin::IPhoneOS ||
3400 TargetPlatform == Darwin::TvOS) &&
3401 getTriple().getArchName() == "arm64e" &&
3402 TargetVersion.getMajor() < 14) {
3403 // arm64e slice is supported on iOS/tvOS 14+ only.
3404 TargetVersion = VersionTuple(14, 0);
3406 VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
3407 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
3408 TargetVersion = MinTgtVers;
3409 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3411 if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
3412 // Mac Catalyst programs must use the appropriate iOS SDK version
3413 // that corresponds to the macOS SDK version used for the compilation.
3414 std::optional<VersionTuple> iOSSDKVersion;
3415 if (SDKInfo) {
3416 if (const auto *MacOStoMacCatalystMapping =
3417 SDKInfo->getVersionMapping(
3418 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
3419 iOSSDKVersion = MacOStoMacCatalystMapping->map(
3420 SDKInfo->getVersion().withoutBuild(),
3421 minimumMacCatalystDeploymentTarget(), std::nullopt);
3424 CmdArgs.push_back(Args.MakeArgString(
3425 (iOSSDKVersion ? *iOSSDKVersion
3426 : minimumMacCatalystDeploymentTarget())
3427 .getAsString()));
3428 return;
3431 if (SDKInfo) {
3432 VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
3433 if (!SDKVersion.getMinor())
3434 SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
3435 CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
3436 } else {
3437 // Use an SDK version that's matching the deployment target if the SDK
3438 // version is missing. This is preferred over an empty SDK version
3439 // (0.0.0) as the system's runtime might expect the linked binary to
3440 // contain a valid SDK version in order for the binary to work
3441 // correctly. It's reasonable to use the deployment target version as
3442 // a proxy for the SDK version because older SDKs don't guarantee
3443 // support for deployment targets newer than the SDK versions, so that
3444 // rules out using some predetermined older SDK version, which leaves
3445 // the deployment target version as the only reasonable choice.
3446 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
3449 EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
3450 TargetEnvironment, getEffectiveTriple());
3451 if (!TargetVariantTriple)
3452 return;
3453 Darwin::DarwinPlatformKind Platform;
3454 Darwin::DarwinEnvironmentKind Environment;
3455 VersionTuple TargetVariantVersion;
3456 if (TargetVariantTriple->isMacOSX()) {
3457 TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);
3458 Platform = Darwin::MacOS;
3459 Environment = Darwin::NativeEnvironment;
3460 } else {
3461 assert(TargetVariantTriple->isiOS() &&
3462 TargetVariantTriple->isMacCatalystEnvironment() &&
3463 "unexpected target variant triple");
3464 TargetVariantVersion = TargetVariantTriple->getiOSVersion();
3465 Platform = Darwin::IPhoneOS;
3466 Environment = Darwin::MacCatalyst;
3468 EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
3469 *TargetVariantTriple);
3472 // Add additional link args for the -dynamiclib option.
3473 static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
3474 ArgStringList &CmdArgs) {
3475 // Derived from darwin_dylib1 spec.
3476 if (D.isTargetIPhoneOS()) {
3477 if (D.isIPhoneOSVersionLT(3, 1))
3478 CmdArgs.push_back("-ldylib1.o");
3479 return;
3482 if (!D.isTargetMacOS())
3483 return;
3484 if (D.isMacosxVersionLT(10, 5))
3485 CmdArgs.push_back("-ldylib1.o");
3486 else if (D.isMacosxVersionLT(10, 6))
3487 CmdArgs.push_back("-ldylib1.10.5.o");
3490 // Add additional link args for the -bundle option.
3491 static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
3492 ArgStringList &CmdArgs) {
3493 if (Args.hasArg(options::OPT_static))
3494 return;
3495 // Derived from darwin_bundle1 spec.
3496 if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
3497 (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
3498 CmdArgs.push_back("-lbundle1.o");
3501 // Add additional link args for the -pg option.
3502 static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
3503 ArgStringList &CmdArgs) {
3504 if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
3505 if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
3506 Args.hasArg(options::OPT_preload)) {
3507 CmdArgs.push_back("-lgcrt0.o");
3508 } else {
3509 CmdArgs.push_back("-lgcrt1.o");
3511 // darwin_crt2 spec is empty.
3513 // By default on OS X 10.8 and later, we don't link with a crt1.o
3514 // file and the linker knows to use _main as the entry point. But,
3515 // when compiling with -pg, we need to link with the gcrt1.o file,
3516 // so pass the -no_new_main option to tell the linker to use the
3517 // "start" symbol as the entry point.
3518 if (!D.isMacosxVersionLT(10, 8))
3519 CmdArgs.push_back("-no_new_main");
3520 } else {
3521 D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
3522 << D.isTargetMacOSBased();
3526 static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
3527 ArgStringList &CmdArgs) {
3528 // Derived from darwin_crt1 spec.
3529 if (D.isTargetIPhoneOS()) {
3530 if (D.getArch() == llvm::Triple::aarch64)
3531 ; // iOS does not need any crt1 files for arm64
3532 else if (D.isIPhoneOSVersionLT(3, 1))
3533 CmdArgs.push_back("-lcrt1.o");
3534 else if (D.isIPhoneOSVersionLT(6, 0))
3535 CmdArgs.push_back("-lcrt1.3.1.o");
3536 return;
3539 if (!D.isTargetMacOS())
3540 return;
3541 if (D.isMacosxVersionLT(10, 5))
3542 CmdArgs.push_back("-lcrt1.o");
3543 else if (D.isMacosxVersionLT(10, 6))
3544 CmdArgs.push_back("-lcrt1.10.5.o");
3545 else if (D.isMacosxVersionLT(10, 8))
3546 CmdArgs.push_back("-lcrt1.10.6.o");
3547 // darwin_crt2 spec is empty.
3550 void Darwin::addStartObjectFileArgs(const ArgList &Args,
3551 ArgStringList &CmdArgs) const {
3552 // Derived from startfile spec.
3553 if (Args.hasArg(options::OPT_dynamiclib))
3554 addDynamicLibLinkArgs(*this, Args, CmdArgs);
3555 else if (Args.hasArg(options::OPT_bundle))
3556 addBundleLinkArgs(*this, Args, CmdArgs);
3557 else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
3558 addPgProfilingLinkArgs(*this, Args, CmdArgs);
3559 else if (Args.hasArg(options::OPT_static) ||
3560 Args.hasArg(options::OPT_object) ||
3561 Args.hasArg(options::OPT_preload))
3562 CmdArgs.push_back("-lcrt0.o");
3563 else
3564 addDefaultCRTLinkArgs(*this, Args, CmdArgs);
3566 if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
3567 isMacosxVersionLT(10, 5)) {
3568 const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
3569 CmdArgs.push_back(Str);
3573 void Darwin::CheckObjCARC() const {
3574 if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||
3575 (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
3576 return;
3577 getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
3580 SanitizerMask Darwin::getSupportedSanitizers() const {
3581 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
3582 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
3583 SanitizerMask Res = ToolChain::getSupportedSanitizers();
3584 Res |= SanitizerKind::Address;
3585 Res |= SanitizerKind::PointerCompare;
3586 Res |= SanitizerKind::PointerSubtract;
3587 Res |= SanitizerKind::Realtime;
3588 Res |= SanitizerKind::Leak;
3589 Res |= SanitizerKind::Fuzzer;
3590 Res |= SanitizerKind::FuzzerNoLink;
3591 Res |= SanitizerKind::ObjCCast;
3593 // Prior to 10.9, macOS shipped a version of the C++ standard library without
3594 // C++11 support. The same is true of iOS prior to version 5. These OS'es are
3595 // incompatible with -fsanitize=vptr.
3596 if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&
3597 !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
3598 Res |= SanitizerKind::Vptr;
3600 if ((IsX86_64 || IsAArch64) &&
3601 (isTargetMacOSBased() || isTargetIOSSimulator() ||
3602 isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
3603 Res |= SanitizerKind::Thread;
3606 if (IsX86_64)
3607 Res |= SanitizerKind::NumericalStability;
3609 return Res;
3612 void Darwin::printVerboseInfo(raw_ostream &OS) const {
3613 CudaInstallation->print(OS);
3614 RocmInstallation->print(OS);