Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
35234 views
1
//===- ToolChain.cpp - Collections of tools for one platform --------------===//
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 "clang/Driver/ToolChain.h"
10
#include "ToolChains/Arch/AArch64.h"
11
#include "ToolChains/Arch/ARM.h"
12
#include "ToolChains/Clang.h"
13
#include "ToolChains/CommonArgs.h"
14
#include "ToolChains/Flang.h"
15
#include "ToolChains/InterfaceStubs.h"
16
#include "clang/Basic/ObjCRuntime.h"
17
#include "clang/Basic/Sanitizers.h"
18
#include "clang/Config/config.h"
19
#include "clang/Driver/Action.h"
20
#include "clang/Driver/Driver.h"
21
#include "clang/Driver/DriverDiagnostic.h"
22
#include "clang/Driver/InputInfo.h"
23
#include "clang/Driver/Job.h"
24
#include "clang/Driver/Options.h"
25
#include "clang/Driver/SanitizerArgs.h"
26
#include "clang/Driver/XRayArgs.h"
27
#include "llvm/ADT/STLExtras.h"
28
#include "llvm/ADT/SmallString.h"
29
#include "llvm/ADT/StringExtras.h"
30
#include "llvm/ADT/StringRef.h"
31
#include "llvm/ADT/Twine.h"
32
#include "llvm/Config/llvm-config.h"
33
#include "llvm/MC/MCTargetOptions.h"
34
#include "llvm/MC/TargetRegistry.h"
35
#include "llvm/Option/Arg.h"
36
#include "llvm/Option/ArgList.h"
37
#include "llvm/Option/OptTable.h"
38
#include "llvm/Option/Option.h"
39
#include "llvm/Support/ErrorHandling.h"
40
#include "llvm/Support/FileSystem.h"
41
#include "llvm/Support/FileUtilities.h"
42
#include "llvm/Support/Path.h"
43
#include "llvm/Support/VersionTuple.h"
44
#include "llvm/Support/VirtualFileSystem.h"
45
#include "llvm/TargetParser/AArch64TargetParser.h"
46
#include "llvm/TargetParser/TargetParser.h"
47
#include "llvm/TargetParser/Triple.h"
48
#include <cassert>
49
#include <cstddef>
50
#include <cstring>
51
#include <string>
52
53
using namespace clang;
54
using namespace driver;
55
using namespace tools;
56
using namespace llvm;
57
using namespace llvm::opt;
58
59
static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
60
return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
61
options::OPT_fno_rtti, options::OPT_frtti);
62
}
63
64
static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
65
const llvm::Triple &Triple,
66
const Arg *CachedRTTIArg) {
67
// Explicit rtti/no-rtti args
68
if (CachedRTTIArg) {
69
if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
70
return ToolChain::RM_Enabled;
71
else
72
return ToolChain::RM_Disabled;
73
}
74
75
// -frtti is default, except for the PS4/PS5 and DriverKit.
76
bool NoRTTI = Triple.isPS() || Triple.isDriverKit();
77
return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
78
}
79
80
static ToolChain::ExceptionsMode CalculateExceptionsMode(const ArgList &Args) {
81
if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
82
true)) {
83
return ToolChain::EM_Enabled;
84
}
85
return ToolChain::EM_Disabled;
86
}
87
88
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
89
const ArgList &Args)
90
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
91
CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),
92
CachedExceptionsMode(CalculateExceptionsMode(Args)) {
93
auto addIfExists = [this](path_list &List, const std::string &Path) {
94
if (getVFS().exists(Path))
95
List.push_back(Path);
96
};
97
98
if (std::optional<std::string> Path = getRuntimePath())
99
getLibraryPaths().push_back(*Path);
100
if (std::optional<std::string> Path = getStdlibPath())
101
getFilePaths().push_back(*Path);
102
for (const auto &Path : getArchSpecificLibPaths())
103
addIfExists(getFilePaths(), Path);
104
}
105
106
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
107
ToolChain::executeToolChainProgram(StringRef Executable,
108
unsigned SecondsToWait) const {
109
llvm::SmallString<64> OutputFile;
110
llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
111
llvm::FileRemover OutputRemover(OutputFile.c_str());
112
std::optional<llvm::StringRef> Redirects[] = {
113
{""},
114
OutputFile.str(),
115
{""},
116
};
117
118
std::string ErrorMessage;
119
if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, SecondsToWait,
120
/*MemoryLimit=*/0, &ErrorMessage))
121
return llvm::createStringError(std::error_code(),
122
Executable + ": " + ErrorMessage);
123
124
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
125
llvm::MemoryBuffer::getFile(OutputFile.c_str());
126
if (!OutputBuf)
127
return llvm::createStringError(OutputBuf.getError(),
128
"Failed to read stdout of " + Executable +
129
": " + OutputBuf.getError().message());
130
return std::move(*OutputBuf);
131
}
132
133
void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
134
Triple.setEnvironment(Env);
135
if (EffectiveTriple != llvm::Triple())
136
EffectiveTriple.setEnvironment(Env);
137
}
138
139
ToolChain::~ToolChain() = default;
140
141
llvm::vfs::FileSystem &ToolChain::getVFS() const {
142
return getDriver().getVFS();
143
}
144
145
bool ToolChain::useIntegratedAs() const {
146
return Args.hasFlag(options::OPT_fintegrated_as,
147
options::OPT_fno_integrated_as,
148
IsIntegratedAssemblerDefault());
149
}
150
151
bool ToolChain::useIntegratedBackend() const {
152
assert(
153
((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||
154
(!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&
155
"(Non-)integrated backend set incorrectly!");
156
157
bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,
158
options::OPT_fno_integrated_objemitter,
159
IsIntegratedBackendDefault());
160
161
// Diagnose when integrated-objemitter options are not supported by this
162
// toolchain.
163
unsigned DiagID;
164
if ((IBackend && !IsIntegratedBackendSupported()) ||
165
(!IBackend && !IsNonIntegratedBackendSupported()))
166
DiagID = clang::diag::err_drv_unsupported_opt_for_target;
167
else
168
DiagID = clang::diag::warn_drv_unsupported_opt_for_target;
169
Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);
170
if (A && !IsNonIntegratedBackendSupported())
171
D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
172
A = Args.getLastArg(options::OPT_fintegrated_objemitter);
173
if (A && !IsIntegratedBackendSupported())
174
D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
175
176
return IBackend;
177
}
178
179
bool ToolChain::useRelaxRelocations() const {
180
return ENABLE_X86_RELAX_RELOCATIONS;
181
}
182
183
bool ToolChain::defaultToIEEELongDouble() const {
184
return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
185
}
186
187
static void getAArch64MultilibFlags(const Driver &D,
188
const llvm::Triple &Triple,
189
const llvm::opt::ArgList &Args,
190
Multilib::flags_list &Result) {
191
std::vector<StringRef> Features;
192
tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);
193
const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
194
llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
195
UnifiedFeatures.end());
196
std::vector<std::string> MArch;
197
for (const auto &Ext : AArch64::Extensions)
198
if (!Ext.UserVisibleName.empty())
199
if (FeatureSet.contains(Ext.PosTargetFeature))
200
MArch.push_back(Ext.UserVisibleName.str());
201
for (const auto &Ext : AArch64::Extensions)
202
if (!Ext.UserVisibleName.empty())
203
if (FeatureSet.contains(Ext.NegTargetFeature))
204
MArch.push_back(("no" + Ext.UserVisibleName).str());
205
StringRef ArchName;
206
for (const auto &ArchInfo : AArch64::ArchInfos)
207
if (FeatureSet.contains(ArchInfo->ArchFeature))
208
ArchName = ArchInfo->Name;
209
assert(!ArchName.empty() && "at least one architecture should be found");
210
MArch.insert(MArch.begin(), ("-march=" + ArchName).str());
211
Result.push_back(llvm::join(MArch, "+"));
212
}
213
214
static void getARMMultilibFlags(const Driver &D,
215
const llvm::Triple &Triple,
216
const llvm::opt::ArgList &Args,
217
Multilib::flags_list &Result) {
218
std::vector<StringRef> Features;
219
llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(
220
D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);
221
const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
222
llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
223
UnifiedFeatures.end());
224
std::vector<std::string> MArch;
225
for (const auto &Ext : ARM::ARCHExtNames)
226
if (!Ext.Name.empty())
227
if (FeatureSet.contains(Ext.Feature))
228
MArch.push_back(Ext.Name.str());
229
for (const auto &Ext : ARM::ARCHExtNames)
230
if (!Ext.Name.empty())
231
if (FeatureSet.contains(Ext.NegFeature))
232
MArch.push_back(("no" + Ext.Name).str());
233
MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
234
Result.push_back(llvm::join(MArch, "+"));
235
236
switch (FPUKind) {
237
#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
238
case llvm::ARM::KIND: \
239
Result.push_back("-mfpu=" NAME); \
240
break;
241
#include "llvm/TargetParser/ARMTargetParser.def"
242
default:
243
llvm_unreachable("Invalid FPUKind");
244
}
245
246
switch (arm::getARMFloatABI(D, Triple, Args)) {
247
case arm::FloatABI::Soft:
248
Result.push_back("-mfloat-abi=soft");
249
break;
250
case arm::FloatABI::SoftFP:
251
Result.push_back("-mfloat-abi=softfp");
252
break;
253
case arm::FloatABI::Hard:
254
Result.push_back("-mfloat-abi=hard");
255
break;
256
case arm::FloatABI::Invalid:
257
llvm_unreachable("Invalid float ABI");
258
}
259
}
260
261
Multilib::flags_list
262
ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
263
using namespace clang::driver::options;
264
265
std::vector<std::string> Result;
266
const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
267
Result.push_back("--target=" + Triple.str());
268
269
switch (Triple.getArch()) {
270
case llvm::Triple::aarch64:
271
case llvm::Triple::aarch64_32:
272
case llvm::Triple::aarch64_be:
273
getAArch64MultilibFlags(D, Triple, Args, Result);
274
break;
275
case llvm::Triple::arm:
276
case llvm::Triple::armeb:
277
case llvm::Triple::thumb:
278
case llvm::Triple::thumbeb:
279
getARMMultilibFlags(D, Triple, Args, Result);
280
break;
281
default:
282
break;
283
}
284
285
// Include fno-exceptions and fno-rtti
286
// to improve multilib selection
287
if (getRTTIMode() == ToolChain::RTTIMode::RM_Disabled)
288
Result.push_back("-fno-rtti");
289
else
290
Result.push_back("-frtti");
291
292
if (getExceptionsMode() == ToolChain::ExceptionsMode::EM_Disabled)
293
Result.push_back("-fno-exceptions");
294
else
295
Result.push_back("-fexceptions");
296
297
// Sort and remove duplicates.
298
std::sort(Result.begin(), Result.end());
299
Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
300
return Result;
301
}
302
303
SanitizerArgs
304
ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
305
SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
306
SanitizerArgsChecked = true;
307
return SanArgs;
308
}
309
310
const XRayArgs& ToolChain::getXRayArgs() const {
311
if (!XRayArguments)
312
XRayArguments.reset(new XRayArgs(*this, Args));
313
return *XRayArguments;
314
}
315
316
namespace {
317
318
struct DriverSuffix {
319
const char *Suffix;
320
const char *ModeFlag;
321
};
322
323
} // namespace
324
325
static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
326
// A list of known driver suffixes. Suffixes are compared against the
327
// program name in order. If there is a match, the frontend type is updated as
328
// necessary by applying the ModeFlag.
329
static const DriverSuffix DriverSuffixes[] = {
330
{"clang", nullptr},
331
{"clang++", "--driver-mode=g++"},
332
{"clang-c++", "--driver-mode=g++"},
333
{"clang-cc", nullptr},
334
{"clang-cpp", "--driver-mode=cpp"},
335
{"clang-g++", "--driver-mode=g++"},
336
{"clang-gcc", nullptr},
337
{"clang-cl", "--driver-mode=cl"},
338
{"cc", nullptr},
339
{"cpp", "--driver-mode=cpp"},
340
{"cl", "--driver-mode=cl"},
341
{"++", "--driver-mode=g++"},
342
{"flang", "--driver-mode=flang"},
343
{"clang-dxc", "--driver-mode=dxc"},
344
};
345
346
for (const auto &DS : DriverSuffixes) {
347
StringRef Suffix(DS.Suffix);
348
if (ProgName.ends_with(Suffix)) {
349
Pos = ProgName.size() - Suffix.size();
350
return &DS;
351
}
352
}
353
return nullptr;
354
}
355
356
/// Normalize the program name from argv[0] by stripping the file extension if
357
/// present and lower-casing the string on Windows.
358
static std::string normalizeProgramName(llvm::StringRef Argv0) {
359
std::string ProgName = std::string(llvm::sys::path::filename(Argv0));
360
if (is_style_windows(llvm::sys::path::Style::native)) {
361
// Transform to lowercase for case insensitive file systems.
362
std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
363
::tolower);
364
}
365
return ProgName;
366
}
367
368
static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
369
// Try to infer frontend type and default target from the program name by
370
// comparing it against DriverSuffixes in order.
371
372
// If there is a match, the function tries to identify a target as prefix.
373
// E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
374
// prefix "x86_64-linux". If such a target prefix is found, it may be
375
// added via -target as implicit first argument.
376
const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
377
378
if (!DS && ProgName.ends_with(".exe")) {
379
// Try again after stripping the executable suffix:
380
// clang++.exe -> clang++
381
ProgName = ProgName.drop_back(StringRef(".exe").size());
382
DS = FindDriverSuffix(ProgName, Pos);
383
}
384
385
if (!DS) {
386
// Try again after stripping any trailing version number:
387
// clang++3.5 -> clang++
388
ProgName = ProgName.rtrim("0123456789.");
389
DS = FindDriverSuffix(ProgName, Pos);
390
}
391
392
if (!DS) {
393
// Try again after stripping trailing -component.
394
// clang++-tot -> clang++
395
ProgName = ProgName.slice(0, ProgName.rfind('-'));
396
DS = FindDriverSuffix(ProgName, Pos);
397
}
398
return DS;
399
}
400
401
ParsedClangName
402
ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
403
std::string ProgName = normalizeProgramName(PN);
404
size_t SuffixPos;
405
const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
406
if (!DS)
407
return {};
408
size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
409
410
size_t LastComponent = ProgName.rfind('-', SuffixPos);
411
if (LastComponent == std::string::npos)
412
return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
413
std::string ModeSuffix = ProgName.substr(LastComponent + 1,
414
SuffixEnd - LastComponent - 1);
415
416
// Infer target from the prefix.
417
StringRef Prefix(ProgName);
418
Prefix = Prefix.slice(0, LastComponent);
419
std::string IgnoredError;
420
bool IsRegistered =
421
llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);
422
return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,
423
IsRegistered};
424
}
425
426
StringRef ToolChain::getDefaultUniversalArchName() const {
427
// In universal driver terms, the arch name accepted by -arch isn't exactly
428
// the same as the ones that appear in the triple. Roughly speaking, this is
429
// an inverse of the darwin::getArchTypeForDarwinArchName() function.
430
switch (Triple.getArch()) {
431
case llvm::Triple::aarch64: {
432
if (getTriple().isArm64e())
433
return "arm64e";
434
return "arm64";
435
}
436
case llvm::Triple::aarch64_32:
437
return "arm64_32";
438
case llvm::Triple::ppc:
439
return "ppc";
440
case llvm::Triple::ppcle:
441
return "ppcle";
442
case llvm::Triple::ppc64:
443
return "ppc64";
444
case llvm::Triple::ppc64le:
445
return "ppc64le";
446
default:
447
return Triple.getArchName();
448
}
449
}
450
451
std::string ToolChain::getInputFilename(const InputInfo &Input) const {
452
return Input.getFilename();
453
}
454
455
ToolChain::UnwindTableLevel
456
ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
457
return UnwindTableLevel::None;
458
}
459
460
Tool *ToolChain::getClang() const {
461
if (!Clang)
462
Clang.reset(new tools::Clang(*this, useIntegratedBackend()));
463
return Clang.get();
464
}
465
466
Tool *ToolChain::getFlang() const {
467
if (!Flang)
468
Flang.reset(new tools::Flang(*this));
469
return Flang.get();
470
}
471
472
Tool *ToolChain::buildAssembler() const {
473
return new tools::ClangAs(*this);
474
}
475
476
Tool *ToolChain::buildLinker() const {
477
llvm_unreachable("Linking is not supported by this toolchain");
478
}
479
480
Tool *ToolChain::buildStaticLibTool() const {
481
llvm_unreachable("Creating static lib is not supported by this toolchain");
482
}
483
484
Tool *ToolChain::getAssemble() const {
485
if (!Assemble)
486
Assemble.reset(buildAssembler());
487
return Assemble.get();
488
}
489
490
Tool *ToolChain::getClangAs() const {
491
if (!Assemble)
492
Assemble.reset(new tools::ClangAs(*this));
493
return Assemble.get();
494
}
495
496
Tool *ToolChain::getLink() const {
497
if (!Link)
498
Link.reset(buildLinker());
499
return Link.get();
500
}
501
502
Tool *ToolChain::getStaticLibTool() const {
503
if (!StaticLibTool)
504
StaticLibTool.reset(buildStaticLibTool());
505
return StaticLibTool.get();
506
}
507
508
Tool *ToolChain::getIfsMerge() const {
509
if (!IfsMerge)
510
IfsMerge.reset(new tools::ifstool::Merger(*this));
511
return IfsMerge.get();
512
}
513
514
Tool *ToolChain::getOffloadBundler() const {
515
if (!OffloadBundler)
516
OffloadBundler.reset(new tools::OffloadBundler(*this));
517
return OffloadBundler.get();
518
}
519
520
Tool *ToolChain::getOffloadPackager() const {
521
if (!OffloadPackager)
522
OffloadPackager.reset(new tools::OffloadPackager(*this));
523
return OffloadPackager.get();
524
}
525
526
Tool *ToolChain::getLinkerWrapper() const {
527
if (!LinkerWrapper)
528
LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
529
return LinkerWrapper.get();
530
}
531
532
Tool *ToolChain::getTool(Action::ActionClass AC) const {
533
switch (AC) {
534
case Action::AssembleJobClass:
535
return getAssemble();
536
537
case Action::IfsMergeJobClass:
538
return getIfsMerge();
539
540
case Action::LinkJobClass:
541
return getLink();
542
543
case Action::StaticLibJobClass:
544
return getStaticLibTool();
545
546
case Action::InputClass:
547
case Action::BindArchClass:
548
case Action::OffloadClass:
549
case Action::LipoJobClass:
550
case Action::DsymutilJobClass:
551
case Action::VerifyDebugInfoJobClass:
552
case Action::BinaryAnalyzeJobClass:
553
llvm_unreachable("Invalid tool kind.");
554
555
case Action::CompileJobClass:
556
case Action::PrecompileJobClass:
557
case Action::PreprocessJobClass:
558
case Action::ExtractAPIJobClass:
559
case Action::AnalyzeJobClass:
560
case Action::MigrateJobClass:
561
case Action::VerifyPCHJobClass:
562
case Action::BackendJobClass:
563
return getClang();
564
565
case Action::OffloadBundlingJobClass:
566
case Action::OffloadUnbundlingJobClass:
567
return getOffloadBundler();
568
569
case Action::OffloadPackagerJobClass:
570
return getOffloadPackager();
571
case Action::LinkerWrapperJobClass:
572
return getLinkerWrapper();
573
}
574
575
llvm_unreachable("Invalid tool kind.");
576
}
577
578
static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
579
const ArgList &Args) {
580
const llvm::Triple &Triple = TC.getTriple();
581
bool IsWindows = Triple.isOSWindows();
582
583
if (TC.isBareMetal())
584
return Triple.getArchName();
585
586
if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
587
return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
588
? "armhf"
589
: "arm";
590
591
// For historic reasons, Android library is using i686 instead of i386.
592
if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
593
return "i686";
594
595
if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())
596
return "x32";
597
598
return llvm::Triple::getArchTypeName(TC.getArch());
599
}
600
601
StringRef ToolChain::getOSLibName() const {
602
if (Triple.isOSDarwin())
603
return "darwin";
604
605
switch (Triple.getOS()) {
606
case llvm::Triple::FreeBSD:
607
return "freebsd";
608
case llvm::Triple::NetBSD:
609
return "netbsd";
610
case llvm::Triple::OpenBSD:
611
return "openbsd";
612
case llvm::Triple::Solaris:
613
return "sunos";
614
case llvm::Triple::AIX:
615
return "aix";
616
default:
617
return getOS();
618
}
619
}
620
621
std::string ToolChain::getCompilerRTPath() const {
622
SmallString<128> Path(getDriver().ResourceDir);
623
if (isBareMetal()) {
624
llvm::sys::path::append(Path, "lib", getOSLibName());
625
if (!SelectedMultilibs.empty()) {
626
Path += SelectedMultilibs.back().gccSuffix();
627
}
628
} else if (Triple.isOSUnknown()) {
629
llvm::sys::path::append(Path, "lib");
630
} else {
631
llvm::sys::path::append(Path, "lib", getOSLibName());
632
}
633
return std::string(Path);
634
}
635
636
std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
637
StringRef Component,
638
FileType Type) const {
639
std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);
640
return llvm::sys::path::filename(CRTAbsolutePath).str();
641
}
642
643
std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
644
StringRef Component,
645
FileType Type,
646
bool AddArch) const {
647
const llvm::Triple &TT = getTriple();
648
bool IsITANMSVCWindows =
649
TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
650
651
const char *Prefix =
652
IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";
653
const char *Suffix;
654
switch (Type) {
655
case ToolChain::FT_Object:
656
Suffix = IsITANMSVCWindows ? ".obj" : ".o";
657
break;
658
case ToolChain::FT_Static:
659
Suffix = IsITANMSVCWindows ? ".lib" : ".a";
660
break;
661
case ToolChain::FT_Shared:
662
Suffix = TT.isOSWindows()
663
? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
664
: ".so";
665
break;
666
}
667
668
std::string ArchAndEnv;
669
if (AddArch) {
670
StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
671
const char *Env = TT.isAndroid() ? "-android" : "";
672
ArchAndEnv = ("-" + Arch + Env).str();
673
}
674
return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();
675
}
676
677
std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
678
FileType Type) const {
679
// Check for runtime files in the new layout without the architecture first.
680
std::string CRTBasename =
681
buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
682
SmallString<128> Path;
683
for (const auto &LibPath : getLibraryPaths()) {
684
SmallString<128> P(LibPath);
685
llvm::sys::path::append(P, CRTBasename);
686
if (getVFS().exists(P))
687
return std::string(P);
688
if (Path.empty())
689
Path = P;
690
}
691
if (getTriple().isOSAIX())
692
Path.clear();
693
694
// Check the filename for the old layout if the new one does not exist.
695
CRTBasename =
696
buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
697
SmallString<128> OldPath(getCompilerRTPath());
698
llvm::sys::path::append(OldPath, CRTBasename);
699
if (Path.empty() || getVFS().exists(OldPath))
700
return std::string(OldPath);
701
702
// If none is found, use a file name from the new layout, which may get
703
// printed in an error message, aiding users in knowing what Clang is
704
// looking for.
705
return std::string(Path);
706
}
707
708
const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
709
StringRef Component,
710
FileType Type) const {
711
return Args.MakeArgString(getCompilerRT(Args, Component, Type));
712
}
713
714
// Android target triples contain a target version. If we don't have libraries
715
// for the exact target version, we should fall back to the next newest version
716
// or a versionless path, if any.
717
std::optional<std::string>
718
ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {
719
llvm::Triple TripleWithoutLevel(getTriple());
720
TripleWithoutLevel.setEnvironmentName("android"); // remove any version number
721
const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();
722
unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();
723
unsigned BestVersion = 0;
724
725
SmallString<32> TripleDir;
726
bool UsingUnversionedDir = false;
727
std::error_code EC;
728
for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;
729
!EC && LI != LE; LI = LI.increment(EC)) {
730
StringRef DirName = llvm::sys::path::filename(LI->path());
731
StringRef DirNameSuffix = DirName;
732
if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {
733
if (DirNameSuffix.empty() && TripleDir.empty()) {
734
TripleDir = DirName;
735
UsingUnversionedDir = true;
736
} else {
737
unsigned Version;
738
if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&
739
Version < TripleVersion) {
740
BestVersion = Version;
741
TripleDir = DirName;
742
UsingUnversionedDir = false;
743
}
744
}
745
}
746
}
747
748
if (TripleDir.empty())
749
return {};
750
751
SmallString<128> P(BaseDir);
752
llvm::sys::path::append(P, TripleDir);
753
if (UsingUnversionedDir)
754
D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();
755
return std::string(P);
756
}
757
758
std::optional<std::string>
759
ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
760
auto getPathForTriple =
761
[&](const llvm::Triple &Triple) -> std::optional<std::string> {
762
SmallString<128> P(BaseDir);
763
llvm::sys::path::append(P, Triple.str());
764
if (getVFS().exists(P))
765
return std::string(P);
766
return {};
767
};
768
769
if (auto Path = getPathForTriple(getTriple()))
770
return *Path;
771
772
// When building with per target runtime directories, various ways of naming
773
// the Arm architecture may have been normalised to simply "arm".
774
// For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".
775
// Since an armv8l system can use libraries built for earlier architecture
776
// versions assuming endian and float ABI match.
777
//
778
// Original triple: armv8l-unknown-linux-gnueabihf
779
// Runtime triple: arm-unknown-linux-gnueabihf
780
//
781
// We do not do this for armeb (big endian) because doing so could make us
782
// select little endian libraries. In addition, all known armeb triples only
783
// use the "armeb" architecture name.
784
//
785
// M profile Arm is bare metal and we know they will not be using the per
786
// target runtime directory layout.
787
if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) {
788
llvm::Triple ArmTriple = getTriple();
789
ArmTriple.setArch(Triple::arm);
790
if (auto Path = getPathForTriple(ArmTriple))
791
return *Path;
792
}
793
794
if (getTriple().isAndroid())
795
return getFallbackAndroidTargetPath(BaseDir);
796
797
return {};
798
}
799
800
std::optional<std::string> ToolChain::getRuntimePath() const {
801
SmallString<128> P(D.ResourceDir);
802
llvm::sys::path::append(P, "lib");
803
if (auto Ret = getTargetSubDirPath(P))
804
return Ret;
805
// Darwin does not use per-target runtime directory.
806
if (Triple.isOSDarwin())
807
return {};
808
llvm::sys::path::append(P, Triple.str());
809
return std::string(P);
810
}
811
812
std::optional<std::string> ToolChain::getStdlibPath() const {
813
SmallString<128> P(D.Dir);
814
llvm::sys::path::append(P, "..", "lib");
815
return getTargetSubDirPath(P);
816
}
817
818
std::optional<std::string> ToolChain::getStdlibIncludePath() const {
819
SmallString<128> P(D.Dir);
820
llvm::sys::path::append(P, "..", "include");
821
return getTargetSubDirPath(P);
822
}
823
824
ToolChain::path_list ToolChain::getArchSpecificLibPaths() const {
825
path_list Paths;
826
827
auto AddPath = [&](const ArrayRef<StringRef> &SS) {
828
SmallString<128> Path(getDriver().ResourceDir);
829
llvm::sys::path::append(Path, "lib");
830
for (auto &S : SS)
831
llvm::sys::path::append(Path, S);
832
Paths.push_back(std::string(Path));
833
};
834
835
AddPath({getTriple().str()});
836
AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())});
837
return Paths;
838
}
839
840
bool ToolChain::needsProfileRT(const ArgList &Args) {
841
if (Args.hasArg(options::OPT_noprofilelib))
842
return false;
843
844
return Args.hasArg(options::OPT_fprofile_generate) ||
845
Args.hasArg(options::OPT_fprofile_generate_EQ) ||
846
Args.hasArg(options::OPT_fcs_profile_generate) ||
847
Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
848
Args.hasArg(options::OPT_fprofile_instr_generate) ||
849
Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
850
Args.hasArg(options::OPT_fcreate_profile) ||
851
Args.hasArg(options::OPT_forder_file_instrumentation);
852
}
853
854
bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
855
return Args.hasArg(options::OPT_coverage) ||
856
Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
857
false);
858
}
859
860
Tool *ToolChain::SelectTool(const JobAction &JA) const {
861
if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
862
if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
863
Action::ActionClass AC = JA.getKind();
864
if (AC == Action::AssembleJobClass && useIntegratedAs() &&
865
!getTriple().isOSAIX())
866
return getClangAs();
867
return getTool(AC);
868
}
869
870
std::string ToolChain::GetFilePath(const char *Name) const {
871
return D.GetFilePath(Name, *this);
872
}
873
874
std::string ToolChain::GetProgramPath(const char *Name) const {
875
return D.GetProgramPath(Name, *this);
876
}
877
878
std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
879
if (LinkerIsLLD)
880
*LinkerIsLLD = false;
881
882
// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
883
// considered as the linker flavor, e.g. "bfd", "gold", or "lld".
884
const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
885
StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
886
887
// --ld-path= takes precedence over -fuse-ld= and specifies the executable
888
// name. -B, COMPILER_PATH and PATH and consulted if the value does not
889
// contain a path component separator.
890
// -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
891
// that --ld-path= points to is lld.
892
if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
893
std::string Path(A->getValue());
894
if (!Path.empty()) {
895
if (llvm::sys::path::parent_path(Path).empty())
896
Path = GetProgramPath(A->getValue());
897
if (llvm::sys::fs::can_execute(Path)) {
898
if (LinkerIsLLD)
899
*LinkerIsLLD = UseLinker == "lld";
900
return std::string(Path);
901
}
902
}
903
getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
904
return GetProgramPath(getDefaultLinker());
905
}
906
// If we're passed -fuse-ld= with no argument, or with the argument ld,
907
// then use whatever the default system linker is.
908
if (UseLinker.empty() || UseLinker == "ld") {
909
const char *DefaultLinker = getDefaultLinker();
910
if (llvm::sys::path::is_absolute(DefaultLinker))
911
return std::string(DefaultLinker);
912
else
913
return GetProgramPath(DefaultLinker);
914
}
915
916
// Extending -fuse-ld= to an absolute or relative path is unexpected. Checking
917
// for the linker flavor is brittle. In addition, prepending "ld." or "ld64."
918
// to a relative path is surprising. This is more complex due to priorities
919
// among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.
920
if (UseLinker.contains('/'))
921
getDriver().Diag(diag::warn_drv_fuse_ld_path);
922
923
if (llvm::sys::path::is_absolute(UseLinker)) {
924
// If we're passed what looks like an absolute path, don't attempt to
925
// second-guess that.
926
if (llvm::sys::fs::can_execute(UseLinker))
927
return std::string(UseLinker);
928
} else {
929
llvm::SmallString<8> LinkerName;
930
if (Triple.isOSDarwin())
931
LinkerName.append("ld64.");
932
else
933
LinkerName.append("ld.");
934
LinkerName.append(UseLinker);
935
936
std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
937
if (llvm::sys::fs::can_execute(LinkerPath)) {
938
if (LinkerIsLLD)
939
*LinkerIsLLD = UseLinker == "lld";
940
return LinkerPath;
941
}
942
}
943
944
if (A)
945
getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
946
947
return GetProgramPath(getDefaultLinker());
948
}
949
950
std::string ToolChain::GetStaticLibToolPath() const {
951
// TODO: Add support for static lib archiving on Windows
952
if (Triple.isOSDarwin())
953
return GetProgramPath("libtool");
954
return GetProgramPath("llvm-ar");
955
}
956
957
types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
958
types::ID id = types::lookupTypeForExtension(Ext);
959
960
// Flang always runs the preprocessor and has no notion of "preprocessed
961
// fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
962
// them differently.
963
if (D.IsFlangMode() && id == types::TY_PP_Fortran)
964
id = types::TY_Fortran;
965
966
return id;
967
}
968
969
bool ToolChain::HasNativeLLVMSupport() const {
970
return false;
971
}
972
973
bool ToolChain::isCrossCompiling() const {
974
llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
975
switch (HostTriple.getArch()) {
976
// The A32/T32/T16 instruction sets are not separate architectures in this
977
// context.
978
case llvm::Triple::arm:
979
case llvm::Triple::armeb:
980
case llvm::Triple::thumb:
981
case llvm::Triple::thumbeb:
982
return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
983
getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
984
default:
985
return HostTriple.getArch() != getArch();
986
}
987
}
988
989
ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
990
return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
991
VersionTuple());
992
}
993
994
llvm::ExceptionHandling
995
ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
996
return llvm::ExceptionHandling::None;
997
}
998
999
bool ToolChain::isThreadModelSupported(const StringRef Model) const {
1000
if (Model == "single") {
1001
// FIXME: 'single' is only supported on ARM and WebAssembly so far.
1002
return Triple.getArch() == llvm::Triple::arm ||
1003
Triple.getArch() == llvm::Triple::armeb ||
1004
Triple.getArch() == llvm::Triple::thumb ||
1005
Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm();
1006
} else if (Model == "posix")
1007
return true;
1008
1009
return false;
1010
}
1011
1012
std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
1013
types::ID InputType) const {
1014
switch (getTriple().getArch()) {
1015
default:
1016
return getTripleString();
1017
1018
case llvm::Triple::x86_64: {
1019
llvm::Triple Triple = getTriple();
1020
if (!Triple.isOSBinFormatMachO())
1021
return getTripleString();
1022
1023
if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
1024
// x86_64h goes in the triple. Other -march options just use the
1025
// vanilla triple we already have.
1026
StringRef MArch = A->getValue();
1027
if (MArch == "x86_64h")
1028
Triple.setArchName(MArch);
1029
}
1030
return Triple.getTriple();
1031
}
1032
case llvm::Triple::aarch64: {
1033
llvm::Triple Triple = getTriple();
1034
tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple);
1035
if (!Triple.isOSBinFormatMachO())
1036
return Triple.getTriple();
1037
1038
if (Triple.isArm64e())
1039
return Triple.getTriple();
1040
1041
// FIXME: older versions of ld64 expect the "arm64" component in the actual
1042
// triple string and query it to determine whether an LTO file can be
1043
// handled. Remove this when we don't care any more.
1044
Triple.setArchName("arm64");
1045
return Triple.getTriple();
1046
}
1047
case llvm::Triple::aarch64_32:
1048
return getTripleString();
1049
case llvm::Triple::arm:
1050
case llvm::Triple::armeb:
1051
case llvm::Triple::thumb:
1052
case llvm::Triple::thumbeb: {
1053
llvm::Triple Triple = getTriple();
1054
tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);
1055
tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);
1056
return Triple.getTriple();
1057
}
1058
}
1059
}
1060
1061
std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1062
types::ID InputType) const {
1063
return ComputeLLVMTriple(Args, InputType);
1064
}
1065
1066
std::string ToolChain::computeSysRoot() const {
1067
return D.SysRoot;
1068
}
1069
1070
void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1071
ArgStringList &CC1Args) const {
1072
// Each toolchain should provide the appropriate include flags.
1073
}
1074
1075
void ToolChain::addClangTargetOptions(
1076
const ArgList &DriverArgs, ArgStringList &CC1Args,
1077
Action::OffloadKind DeviceOffloadKind) const {}
1078
1079
void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
1080
ArgStringList &CC1ASArgs) const {}
1081
1082
void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
1083
1084
void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
1085
llvm::opt::ArgStringList &CmdArgs) const {
1086
if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1087
return;
1088
1089
CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
1090
}
1091
1092
ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
1093
const ArgList &Args) const {
1094
if (runtimeLibType)
1095
return *runtimeLibType;
1096
1097
const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
1098
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
1099
1100
// Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
1101
if (LibName == "compiler-rt")
1102
runtimeLibType = ToolChain::RLT_CompilerRT;
1103
else if (LibName == "libgcc")
1104
runtimeLibType = ToolChain::RLT_Libgcc;
1105
else if (LibName == "platform")
1106
runtimeLibType = GetDefaultRuntimeLibType();
1107
else {
1108
if (A)
1109
getDriver().Diag(diag::err_drv_invalid_rtlib_name)
1110
<< A->getAsString(Args);
1111
1112
runtimeLibType = GetDefaultRuntimeLibType();
1113
}
1114
1115
return *runtimeLibType;
1116
}
1117
1118
ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
1119
const ArgList &Args) const {
1120
if (unwindLibType)
1121
return *unwindLibType;
1122
1123
const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
1124
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;
1125
1126
if (LibName == "none")
1127
unwindLibType = ToolChain::UNW_None;
1128
else if (LibName == "platform" || LibName == "") {
1129
ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
1130
if (RtLibType == ToolChain::RLT_CompilerRT) {
1131
if (getTriple().isAndroid() || getTriple().isOSAIX())
1132
unwindLibType = ToolChain::UNW_CompilerRT;
1133
else
1134
unwindLibType = ToolChain::UNW_None;
1135
} else if (RtLibType == ToolChain::RLT_Libgcc)
1136
unwindLibType = ToolChain::UNW_Libgcc;
1137
} else if (LibName == "libunwind") {
1138
if (GetRuntimeLibType(Args) == RLT_Libgcc)
1139
getDriver().Diag(diag::err_drv_incompatible_unwindlib);
1140
unwindLibType = ToolChain::UNW_CompilerRT;
1141
} else if (LibName == "libgcc")
1142
unwindLibType = ToolChain::UNW_Libgcc;
1143
else {
1144
if (A)
1145
getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
1146
<< A->getAsString(Args);
1147
1148
unwindLibType = GetDefaultUnwindLibType();
1149
}
1150
1151
return *unwindLibType;
1152
}
1153
1154
ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
1155
if (cxxStdlibType)
1156
return *cxxStdlibType;
1157
1158
const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
1159
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
1160
1161
// Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
1162
if (LibName == "libc++")
1163
cxxStdlibType = ToolChain::CST_Libcxx;
1164
else if (LibName == "libstdc++")
1165
cxxStdlibType = ToolChain::CST_Libstdcxx;
1166
else if (LibName == "platform")
1167
cxxStdlibType = GetDefaultCXXStdlibType();
1168
else {
1169
if (A)
1170
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
1171
<< A->getAsString(Args);
1172
1173
cxxStdlibType = GetDefaultCXXStdlibType();
1174
}
1175
1176
return *cxxStdlibType;
1177
}
1178
1179
/// Utility function to add a system include directory to CC1 arguments.
1180
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
1181
ArgStringList &CC1Args,
1182
const Twine &Path) {
1183
CC1Args.push_back("-internal-isystem");
1184
CC1Args.push_back(DriverArgs.MakeArgString(Path));
1185
}
1186
1187
/// Utility function to add a system include directory with extern "C"
1188
/// semantics to CC1 arguments.
1189
///
1190
/// Note that this should be used rarely, and only for directories that
1191
/// historically and for legacy reasons are treated as having implicit extern
1192
/// "C" semantics. These semantics are *ignored* by and large today, but its
1193
/// important to preserve the preprocessor changes resulting from the
1194
/// classification.
1195
/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
1196
ArgStringList &CC1Args,
1197
const Twine &Path) {
1198
CC1Args.push_back("-internal-externc-isystem");
1199
CC1Args.push_back(DriverArgs.MakeArgString(Path));
1200
}
1201
1202
void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
1203
ArgStringList &CC1Args,
1204
const Twine &Path) {
1205
if (llvm::sys::fs::exists(Path))
1206
addExternCSystemInclude(DriverArgs, CC1Args, Path);
1207
}
1208
1209
/// Utility function to add a list of system include directories to CC1.
1210
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
1211
ArgStringList &CC1Args,
1212
ArrayRef<StringRef> Paths) {
1213
for (const auto &Path : Paths) {
1214
CC1Args.push_back("-internal-isystem");
1215
CC1Args.push_back(DriverArgs.MakeArgString(Path));
1216
}
1217
}
1218
1219
/*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
1220
const Twine &B, const Twine &C,
1221
const Twine &D) {
1222
SmallString<128> Result(Path);
1223
llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
1224
return std::string(Result);
1225
}
1226
1227
std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
1228
std::error_code EC;
1229
int MaxVersion = 0;
1230
std::string MaxVersionString;
1231
SmallString<128> Path(IncludePath);
1232
llvm::sys::path::append(Path, "c++");
1233
for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
1234
!EC && LI != LE; LI = LI.increment(EC)) {
1235
StringRef VersionText = llvm::sys::path::filename(LI->path());
1236
int Version;
1237
if (VersionText[0] == 'v' &&
1238
!VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
1239
if (Version > MaxVersion) {
1240
MaxVersion = Version;
1241
MaxVersionString = std::string(VersionText);
1242
}
1243
}
1244
}
1245
if (!MaxVersion)
1246
return "";
1247
return MaxVersionString;
1248
}
1249
1250
void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1251
ArgStringList &CC1Args) const {
1252
// Header search paths should be handled by each of the subclasses.
1253
// Historically, they have not been, and instead have been handled inside of
1254
// the CC1-layer frontend. As the logic is hoisted out, this generic function
1255
// will slowly stop being called.
1256
//
1257
// While it is being called, replicate a bit of a hack to propagate the
1258
// '-stdlib=' flag down to CC1 so that it can in turn customize the C++
1259
// header search paths with it. Once all systems are overriding this
1260
// function, the CC1 flag and this line can be removed.
1261
DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
1262
}
1263
1264
void ToolChain::AddClangCXXStdlibIsystemArgs(
1265
const llvm::opt::ArgList &DriverArgs,
1266
llvm::opt::ArgStringList &CC1Args) const {
1267
DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
1268
// This intentionally only looks at -nostdinc++, and not -nostdinc or
1269
// -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain
1270
// setups with non-standard search logic for the C++ headers, while still
1271
// allowing users of the toolchain to bring their own C++ headers. Such a
1272
// toolchain likely also has non-standard search logic for the C headers and
1273
// uses -nostdinc to suppress the default logic, but -stdlib++-isystem should
1274
// still work in that case and only be suppressed by an explicit -nostdinc++
1275
// in a project using the toolchain.
1276
if (!DriverArgs.hasArg(options::OPT_nostdincxx))
1277
for (const auto &P :
1278
DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
1279
addSystemInclude(DriverArgs, CC1Args, P);
1280
}
1281
1282
bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {
1283
return getDriver().CCCIsCXX() &&
1284
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
1285
options::OPT_nostdlibxx);
1286
}
1287
1288
void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
1289
ArgStringList &CmdArgs) const {
1290
assert(!Args.hasArg(options::OPT_nostdlibxx) &&
1291
"should not have called this");
1292
CXXStdlibType Type = GetCXXStdlibType(Args);
1293
1294
switch (Type) {
1295
case ToolChain::CST_Libcxx:
1296
CmdArgs.push_back("-lc++");
1297
if (Args.hasArg(options::OPT_fexperimental_library))
1298
CmdArgs.push_back("-lc++experimental");
1299
break;
1300
1301
case ToolChain::CST_Libstdcxx:
1302
CmdArgs.push_back("-lstdc++");
1303
break;
1304
}
1305
}
1306
1307
void ToolChain::AddFilePathLibArgs(const ArgList &Args,
1308
ArgStringList &CmdArgs) const {
1309
for (const auto &LibPath : getFilePaths())
1310
if(LibPath.length() > 0)
1311
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
1312
}
1313
1314
void ToolChain::AddCCKextLibArgs(const ArgList &Args,
1315
ArgStringList &CmdArgs) const {
1316
CmdArgs.push_back("-lcc_kext");
1317
}
1318
1319
bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
1320
std::string &Path) const {
1321
// Don't implicitly link in mode-changing libraries in a shared library, since
1322
// this can have very deleterious effects. See the various links from
1323
// https://github.com/llvm/llvm-project/issues/57589 for more information.
1324
bool Default = !Args.hasArgNoClaim(options::OPT_shared);
1325
1326
// Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
1327
// (to keep the linker options consistent with gcc and clang itself).
1328
if (Default && !isOptimizationLevelFast(Args)) {
1329
// Check if -ffast-math or -funsafe-math.
1330
Arg *A = Args.getLastArg(
1331
options::OPT_ffast_math, options::OPT_fno_fast_math,
1332
options::OPT_funsafe_math_optimizations,
1333
options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ);
1334
1335
if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
1336
A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
1337
Default = false;
1338
if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) {
1339
StringRef Model = A->getValue();
1340
if (Model != "fast")
1341
Default = false;
1342
}
1343
}
1344
1345
// Whatever decision came as a result of the above implicit settings, either
1346
// -mdaz-ftz or -mno-daz-ftz is capable of overriding it.
1347
if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default))
1348
return false;
1349
1350
// If crtfastmath.o exists add it to the arguments.
1351
Path = GetFilePath("crtfastmath.o");
1352
return (Path != "crtfastmath.o"); // Not found.
1353
}
1354
1355
bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
1356
ArgStringList &CmdArgs) const {
1357
std::string Path;
1358
if (isFastMathRuntimeAvailable(Args, Path)) {
1359
CmdArgs.push_back(Args.MakeArgString(Path));
1360
return true;
1361
}
1362
1363
return false;
1364
}
1365
1366
Expected<SmallVector<std::string>>
1367
ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
1368
return SmallVector<std::string>();
1369
}
1370
1371
SanitizerMask ToolChain::getSupportedSanitizers() const {
1372
// Return sanitizers which don't require runtime support and are not
1373
// platform dependent.
1374
1375
SanitizerMask Res =
1376
(SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
1377
(SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
1378
SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
1379
SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
1380
SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
1381
SanitizerKind::Nullability | SanitizerKind::LocalBounds;
1382
if (getTriple().getArch() == llvm::Triple::x86 ||
1383
getTriple().getArch() == llvm::Triple::x86_64 ||
1384
getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||
1385
getTriple().isAArch64() || getTriple().isRISCV() ||
1386
getTriple().isLoongArch64())
1387
Res |= SanitizerKind::CFIICall;
1388
if (getTriple().getArch() == llvm::Triple::x86_64 ||
1389
getTriple().isAArch64(64) || getTriple().isRISCV())
1390
Res |= SanitizerKind::ShadowCallStack;
1391
if (getTriple().isAArch64(64))
1392
Res |= SanitizerKind::MemTag;
1393
return Res;
1394
}
1395
1396
void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
1397
ArgStringList &CC1Args) const {}
1398
1399
void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
1400
ArgStringList &CC1Args) const {}
1401
1402
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
1403
ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
1404
return {};
1405
}
1406
1407
void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
1408
ArgStringList &CC1Args) const {}
1409
1410
static VersionTuple separateMSVCFullVersion(unsigned Version) {
1411
if (Version < 100)
1412
return VersionTuple(Version);
1413
1414
if (Version < 10000)
1415
return VersionTuple(Version / 100, Version % 100);
1416
1417
unsigned Build = 0, Factor = 1;
1418
for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
1419
Build = Build + (Version % 10) * Factor;
1420
return VersionTuple(Version / 100, Version % 100, Build);
1421
}
1422
1423
VersionTuple
1424
ToolChain::computeMSVCVersion(const Driver *D,
1425
const llvm::opt::ArgList &Args) const {
1426
const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
1427
const Arg *MSCompatibilityVersion =
1428
Args.getLastArg(options::OPT_fms_compatibility_version);
1429
1430
if (MSCVersion && MSCompatibilityVersion) {
1431
if (D)
1432
D->Diag(diag::err_drv_argument_not_allowed_with)
1433
<< MSCVersion->getAsString(Args)
1434
<< MSCompatibilityVersion->getAsString(Args);
1435
return VersionTuple();
1436
}
1437
1438
if (MSCompatibilityVersion) {
1439
VersionTuple MSVT;
1440
if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {
1441
if (D)
1442
D->Diag(diag::err_drv_invalid_value)
1443
<< MSCompatibilityVersion->getAsString(Args)
1444
<< MSCompatibilityVersion->getValue();
1445
} else {
1446
return MSVT;
1447
}
1448
}
1449
1450
if (MSCVersion) {
1451
unsigned Version = 0;
1452
if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {
1453
if (D)
1454
D->Diag(diag::err_drv_invalid_value)
1455
<< MSCVersion->getAsString(Args) << MSCVersion->getValue();
1456
} else {
1457
return separateMSVCFullVersion(Version);
1458
}
1459
}
1460
1461
return VersionTuple();
1462
}
1463
1464
llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
1465
const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
1466
SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {
1467
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1468
const OptTable &Opts = getDriver().getOpts();
1469
bool Modified = false;
1470
1471
// Handle -Xopenmp-target flags
1472
for (auto *A : Args) {
1473
// Exclude flags which may only apply to the host toolchain.
1474
// Do not exclude flags when the host triple (AuxTriple)
1475
// matches the current toolchain triple. If it is not present
1476
// at all, target and host share a toolchain.
1477
if (A->getOption().matches(options::OPT_m_Group)) {
1478
// Pass code object version to device toolchain
1479
// to correctly set metadata in intermediate files.
1480
if (SameTripleAsHost ||
1481
A->getOption().matches(options::OPT_mcode_object_version_EQ))
1482
DAL->append(A);
1483
else
1484
Modified = true;
1485
continue;
1486
}
1487
1488
unsigned Index;
1489
unsigned Prev;
1490
bool XOpenMPTargetNoTriple =
1491
A->getOption().matches(options::OPT_Xopenmp_target);
1492
1493
if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
1494
llvm::Triple TT(getOpenMPTriple(A->getValue(0)));
1495
1496
// Passing device args: -Xopenmp-target=<triple> -opt=val.
1497
if (TT.getTriple() == getTripleString())
1498
Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
1499
else
1500
continue;
1501
} else if (XOpenMPTargetNoTriple) {
1502
// Passing device args: -Xopenmp-target -opt=val.
1503
Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
1504
} else {
1505
DAL->append(A);
1506
continue;
1507
}
1508
1509
// Parse the argument to -Xopenmp-target.
1510
Prev = Index;
1511
std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
1512
if (!XOpenMPTargetArg || Index > Prev + 1) {
1513
getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
1514
<< A->getAsString(Args);
1515
continue;
1516
}
1517
if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
1518
Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
1519
getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
1520
continue;
1521
}
1522
XOpenMPTargetArg->setBaseArg(A);
1523
A = XOpenMPTargetArg.release();
1524
AllocatedArgs.push_back(A);
1525
DAL->append(A);
1526
Modified = true;
1527
}
1528
1529
if (Modified)
1530
return DAL;
1531
1532
delete DAL;
1533
return nullptr;
1534
}
1535
1536
// TODO: Currently argument values separated by space e.g.
1537
// -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be
1538
// fixed.
1539
void ToolChain::TranslateXarchArgs(
1540
const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,
1541
llvm::opt::DerivedArgList *DAL,
1542
SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1543
const OptTable &Opts = getDriver().getOpts();
1544
unsigned ValuePos = 1;
1545
if (A->getOption().matches(options::OPT_Xarch_device) ||
1546
A->getOption().matches(options::OPT_Xarch_host))
1547
ValuePos = 0;
1548
1549
unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));
1550
unsigned Prev = Index;
1551
std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));
1552
1553
// If the argument parsing failed or more than one argument was
1554
// consumed, the -Xarch_ argument's parameter tried to consume
1555
// extra arguments. Emit an error and ignore.
1556
//
1557
// We also want to disallow any options which would alter the
1558
// driver behavior; that isn't going to work in our model. We
1559
// use options::NoXarchOption to control this.
1560
if (!XarchArg || Index > Prev + 1) {
1561
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
1562
<< A->getAsString(Args);
1563
return;
1564
} else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) {
1565
auto &Diags = getDriver().getDiags();
1566
unsigned DiagID =
1567
Diags.getCustomDiagID(DiagnosticsEngine::Error,
1568
"invalid Xarch argument: '%0', not all driver "
1569
"options can be forwared via Xarch argument");
1570
Diags.Report(DiagID) << A->getAsString(Args);
1571
return;
1572
}
1573
XarchArg->setBaseArg(A);
1574
A = XarchArg.release();
1575
if (!AllocatedArgs)
1576
DAL->AddSynthesizedArg(A);
1577
else
1578
AllocatedArgs->push_back(A);
1579
}
1580
1581
llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
1582
const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
1583
Action::OffloadKind OFK,
1584
SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1585
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1586
bool Modified = false;
1587
1588
bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;
1589
for (Arg *A : Args) {
1590
bool NeedTrans = false;
1591
bool Skip = false;
1592
if (A->getOption().matches(options::OPT_Xarch_device)) {
1593
NeedTrans = IsDevice;
1594
Skip = !IsDevice;
1595
} else if (A->getOption().matches(options::OPT_Xarch_host)) {
1596
NeedTrans = !IsDevice;
1597
Skip = IsDevice;
1598
} else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {
1599
// Do not translate -Xarch_ options for non CUDA/HIP toolchain since
1600
// they may need special translation.
1601
// Skip this argument unless the architecture matches BoundArch
1602
if (BoundArch.empty() || A->getValue(0) != BoundArch)
1603
Skip = true;
1604
else
1605
NeedTrans = true;
1606
}
1607
if (NeedTrans || Skip)
1608
Modified = true;
1609
if (NeedTrans)
1610
TranslateXarchArgs(Args, A, DAL, AllocatedArgs);
1611
if (!Skip)
1612
DAL->append(A);
1613
}
1614
1615
if (Modified)
1616
return DAL;
1617
1618
delete DAL;
1619
return nullptr;
1620
}
1621
1622