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