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