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