[cmake] Add minor version to library SONAME (#79376)
[llvm-project.git] / clang / lib / Driver / ToolChain.cpp
blob388030592b483692133f08ff86bd7b7a2c9c8980
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 //===----------------------------------------------------------------------===//
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>
53 using namespace clang;
54 using namespace driver;
55 using namespace tools;
56 using namespace llvm;
57 using namespace llvm::opt;
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);
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;
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;
80 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
81 const ArgList &Args)
82 : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
83 CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
84 auto addIfExists = [this](path_list &List, const std::string &Path) {
85 if (getVFS().exists(Path))
86 List.push_back(Path);
89 if (std::optional<std::string> Path = getRuntimePath())
90 getLibraryPaths().push_back(*Path);
91 if (std::optional<std::string> Path = getStdlibPath())
92 getFilePaths().push_back(*Path);
93 for (const auto &Path : getArchSpecificLibPaths())
94 addIfExists(getFilePaths(), Path);
97 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
98 ToolChain::executeToolChainProgram(StringRef Executable) const {
99 llvm::SmallString<64> OutputFile;
100 llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
101 llvm::FileRemover OutputRemover(OutputFile.c_str());
102 std::optional<llvm::StringRef> Redirects[] = {
103 {""},
104 OutputFile.str(),
105 {""},
108 std::string ErrorMessage;
109 if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects,
110 /* SecondsToWait */ 0,
111 /*MemoryLimit*/ 0, &ErrorMessage))
112 return llvm::createStringError(std::error_code(),
113 Executable + ": " + ErrorMessage);
115 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
116 llvm::MemoryBuffer::getFile(OutputFile.c_str());
117 if (!OutputBuf)
118 return llvm::createStringError(OutputBuf.getError(),
119 "Failed to read stdout of " + Executable +
120 ": " + OutputBuf.getError().message());
121 return std::move(*OutputBuf);
124 void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
125 Triple.setEnvironment(Env);
126 if (EffectiveTriple != llvm::Triple())
127 EffectiveTriple.setEnvironment(Env);
130 ToolChain::~ToolChain() = default;
132 llvm::vfs::FileSystem &ToolChain::getVFS() const {
133 return getDriver().getVFS();
136 bool ToolChain::useIntegratedAs() const {
137 return Args.hasFlag(options::OPT_fintegrated_as,
138 options::OPT_fno_integrated_as,
139 IsIntegratedAssemblerDefault());
142 bool ToolChain::useIntegratedBackend() const {
143 assert(
144 ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||
145 (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&
146 "(Non-)integrated backend set incorrectly!");
148 bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,
149 options::OPT_fno_integrated_objemitter,
150 IsIntegratedBackendDefault());
152 // Diagnose when integrated-objemitter options are not supported by this
153 // toolchain.
154 unsigned DiagID;
155 if ((IBackend && !IsIntegratedBackendSupported()) ||
156 (!IBackend && !IsNonIntegratedBackendSupported()))
157 DiagID = clang::diag::err_drv_unsupported_opt_for_target;
158 else
159 DiagID = clang::diag::warn_drv_unsupported_opt_for_target;
160 Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);
161 if (A && !IsNonIntegratedBackendSupported())
162 D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
163 A = Args.getLastArg(options::OPT_fintegrated_objemitter);
164 if (A && !IsIntegratedBackendSupported())
165 D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
167 return IBackend;
170 bool ToolChain::useRelaxRelocations() const {
171 return ENABLE_X86_RELAX_RELOCATIONS;
174 bool ToolChain::defaultToIEEELongDouble() const {
175 return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
178 static void getAArch64MultilibFlags(const Driver &D,
179 const llvm::Triple &Triple,
180 const llvm::opt::ArgList &Args,
181 Multilib::flags_list &Result) {
182 std::vector<StringRef> Features;
183 tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);
184 const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
185 llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
186 UnifiedFeatures.end());
187 std::vector<std::string> MArch;
188 for (const auto &Ext : AArch64::Extensions)
189 if (FeatureSet.contains(Ext.Feature))
190 MArch.push_back(Ext.Name.str());
191 for (const auto &Ext : AArch64::Extensions)
192 if (FeatureSet.contains(Ext.NegFeature))
193 MArch.push_back(("no" + Ext.Name).str());
194 MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
195 Result.push_back(llvm::join(MArch, "+"));
198 static void getARMMultilibFlags(const Driver &D,
199 const llvm::Triple &Triple,
200 const llvm::opt::ArgList &Args,
201 Multilib::flags_list &Result) {
202 std::vector<StringRef> Features;
203 llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(
204 D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);
205 const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
206 llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
207 UnifiedFeatures.end());
208 std::vector<std::string> MArch;
209 for (const auto &Ext : ARM::ARCHExtNames)
210 if (FeatureSet.contains(Ext.Feature))
211 MArch.push_back(Ext.Name.str());
212 for (const auto &Ext : ARM::ARCHExtNames)
213 if (FeatureSet.contains(Ext.NegFeature))
214 MArch.push_back(("no" + Ext.Name).str());
215 MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
216 Result.push_back(llvm::join(MArch, "+"));
218 switch (FPUKind) {
219 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
220 case llvm::ARM::KIND: \
221 Result.push_back("-mfpu=" NAME); \
222 break;
223 #include "llvm/TargetParser/ARMTargetParser.def"
224 default:
225 llvm_unreachable("Invalid FPUKind");
228 switch (arm::getARMFloatABI(D, Triple, Args)) {
229 case arm::FloatABI::Soft:
230 Result.push_back("-mfloat-abi=soft");
231 break;
232 case arm::FloatABI::SoftFP:
233 Result.push_back("-mfloat-abi=softfp");
234 break;
235 case arm::FloatABI::Hard:
236 Result.push_back("-mfloat-abi=hard");
237 break;
238 case arm::FloatABI::Invalid:
239 llvm_unreachable("Invalid float ABI");
243 Multilib::flags_list
244 ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
245 using namespace clang::driver::options;
247 std::vector<std::string> Result;
248 const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
249 Result.push_back("--target=" + Triple.str());
251 switch (Triple.getArch()) {
252 case llvm::Triple::aarch64:
253 case llvm::Triple::aarch64_32:
254 case llvm::Triple::aarch64_be:
255 getAArch64MultilibFlags(D, Triple, Args, Result);
256 break;
257 case llvm::Triple::arm:
258 case llvm::Triple::armeb:
259 case llvm::Triple::thumb:
260 case llvm::Triple::thumbeb:
261 getARMMultilibFlags(D, Triple, Args, Result);
262 break;
263 default:
264 break;
267 // Sort and remove duplicates.
268 std::sort(Result.begin(), Result.end());
269 Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
270 return Result;
273 SanitizerArgs
274 ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
275 SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
276 SanitizerArgsChecked = true;
277 return SanArgs;
280 const XRayArgs& ToolChain::getXRayArgs() const {
281 if (!XRayArguments)
282 XRayArguments.reset(new XRayArgs(*this, Args));
283 return *XRayArguments;
286 namespace {
288 struct DriverSuffix {
289 const char *Suffix;
290 const char *ModeFlag;
293 } // namespace
295 static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
296 // A list of known driver suffixes. Suffixes are compared against the
297 // program name in order. If there is a match, the frontend type is updated as
298 // necessary by applying the ModeFlag.
299 static const DriverSuffix DriverSuffixes[] = {
300 {"clang", nullptr},
301 {"clang++", "--driver-mode=g++"},
302 {"clang-c++", "--driver-mode=g++"},
303 {"clang-cc", nullptr},
304 {"clang-cpp", "--driver-mode=cpp"},
305 {"clang-g++", "--driver-mode=g++"},
306 {"clang-gcc", nullptr},
307 {"clang-cl", "--driver-mode=cl"},
308 {"cc", nullptr},
309 {"cpp", "--driver-mode=cpp"},
310 {"cl", "--driver-mode=cl"},
311 {"++", "--driver-mode=g++"},
312 {"flang", "--driver-mode=flang"},
313 {"clang-dxc", "--driver-mode=dxc"},
316 for (const auto &DS : DriverSuffixes) {
317 StringRef Suffix(DS.Suffix);
318 if (ProgName.ends_with(Suffix)) {
319 Pos = ProgName.size() - Suffix.size();
320 return &DS;
323 return nullptr;
326 /// Normalize the program name from argv[0] by stripping the file extension if
327 /// present and lower-casing the string on Windows.
328 static std::string normalizeProgramName(llvm::StringRef Argv0) {
329 std::string ProgName = std::string(llvm::sys::path::filename(Argv0));
330 if (is_style_windows(llvm::sys::path::Style::native)) {
331 // Transform to lowercase for case insensitive file systems.
332 std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
333 ::tolower);
335 return ProgName;
338 static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
339 // Try to infer frontend type and default target from the program name by
340 // comparing it against DriverSuffixes in order.
342 // If there is a match, the function tries to identify a target as prefix.
343 // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
344 // prefix "x86_64-linux". If such a target prefix is found, it may be
345 // added via -target as implicit first argument.
346 const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
348 if (!DS && ProgName.ends_with(".exe")) {
349 // Try again after stripping the executable suffix:
350 // clang++.exe -> clang++
351 ProgName = ProgName.drop_back(StringRef(".exe").size());
352 DS = FindDriverSuffix(ProgName, Pos);
355 if (!DS) {
356 // Try again after stripping any trailing version number:
357 // clang++3.5 -> clang++
358 ProgName = ProgName.rtrim("0123456789.");
359 DS = FindDriverSuffix(ProgName, Pos);
362 if (!DS) {
363 // Try again after stripping trailing -component.
364 // clang++-tot -> clang++
365 ProgName = ProgName.slice(0, ProgName.rfind('-'));
366 DS = FindDriverSuffix(ProgName, Pos);
368 return DS;
371 ParsedClangName
372 ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
373 std::string ProgName = normalizeProgramName(PN);
374 size_t SuffixPos;
375 const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
376 if (!DS)
377 return {};
378 size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
380 size_t LastComponent = ProgName.rfind('-', SuffixPos);
381 if (LastComponent == std::string::npos)
382 return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
383 std::string ModeSuffix = ProgName.substr(LastComponent + 1,
384 SuffixEnd - LastComponent - 1);
386 // Infer target from the prefix.
387 StringRef Prefix(ProgName);
388 Prefix = Prefix.slice(0, LastComponent);
389 std::string IgnoredError;
390 bool IsRegistered =
391 llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);
392 return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,
393 IsRegistered};
396 StringRef ToolChain::getDefaultUniversalArchName() const {
397 // In universal driver terms, the arch name accepted by -arch isn't exactly
398 // the same as the ones that appear in the triple. Roughly speaking, this is
399 // an inverse of the darwin::getArchTypeForDarwinArchName() function.
400 switch (Triple.getArch()) {
401 case llvm::Triple::aarch64: {
402 if (getTriple().isArm64e())
403 return "arm64e";
404 return "arm64";
406 case llvm::Triple::aarch64_32:
407 return "arm64_32";
408 case llvm::Triple::ppc:
409 return "ppc";
410 case llvm::Triple::ppcle:
411 return "ppcle";
412 case llvm::Triple::ppc64:
413 return "ppc64";
414 case llvm::Triple::ppc64le:
415 return "ppc64le";
416 default:
417 return Triple.getArchName();
421 std::string ToolChain::getInputFilename(const InputInfo &Input) const {
422 return Input.getFilename();
425 ToolChain::UnwindTableLevel
426 ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
427 return UnwindTableLevel::None;
430 unsigned ToolChain::GetDefaultDwarfVersion() const {
431 // TODO: Remove the RISC-V special case when R_RISCV_SET_ULEB128 linker
432 // support becomes more widely available.
433 return getTriple().isRISCV() ? 4 : 5;
436 Tool *ToolChain::getClang() const {
437 if (!Clang)
438 Clang.reset(new tools::Clang(*this, useIntegratedBackend()));
439 return Clang.get();
442 Tool *ToolChain::getFlang() const {
443 if (!Flang)
444 Flang.reset(new tools::Flang(*this));
445 return Flang.get();
448 Tool *ToolChain::buildAssembler() const {
449 return new tools::ClangAs(*this);
452 Tool *ToolChain::buildLinker() const {
453 llvm_unreachable("Linking is not supported by this toolchain");
456 Tool *ToolChain::buildStaticLibTool() const {
457 llvm_unreachable("Creating static lib is not supported by this toolchain");
460 Tool *ToolChain::getAssemble() const {
461 if (!Assemble)
462 Assemble.reset(buildAssembler());
463 return Assemble.get();
466 Tool *ToolChain::getClangAs() const {
467 if (!Assemble)
468 Assemble.reset(new tools::ClangAs(*this));
469 return Assemble.get();
472 Tool *ToolChain::getLink() const {
473 if (!Link)
474 Link.reset(buildLinker());
475 return Link.get();
478 Tool *ToolChain::getStaticLibTool() const {
479 if (!StaticLibTool)
480 StaticLibTool.reset(buildStaticLibTool());
481 return StaticLibTool.get();
484 Tool *ToolChain::getIfsMerge() const {
485 if (!IfsMerge)
486 IfsMerge.reset(new tools::ifstool::Merger(*this));
487 return IfsMerge.get();
490 Tool *ToolChain::getOffloadBundler() const {
491 if (!OffloadBundler)
492 OffloadBundler.reset(new tools::OffloadBundler(*this));
493 return OffloadBundler.get();
496 Tool *ToolChain::getOffloadPackager() const {
497 if (!OffloadPackager)
498 OffloadPackager.reset(new tools::OffloadPackager(*this));
499 return OffloadPackager.get();
502 Tool *ToolChain::getLinkerWrapper() const {
503 if (!LinkerWrapper)
504 LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
505 return LinkerWrapper.get();
508 Tool *ToolChain::getTool(Action::ActionClass AC) const {
509 switch (AC) {
510 case Action::AssembleJobClass:
511 return getAssemble();
513 case Action::IfsMergeJobClass:
514 return getIfsMerge();
516 case Action::LinkJobClass:
517 return getLink();
519 case Action::StaticLibJobClass:
520 return getStaticLibTool();
522 case Action::InputClass:
523 case Action::BindArchClass:
524 case Action::OffloadClass:
525 case Action::LipoJobClass:
526 case Action::DsymutilJobClass:
527 case Action::VerifyDebugInfoJobClass:
528 case Action::BinaryAnalyzeJobClass:
529 llvm_unreachable("Invalid tool kind.");
531 case Action::CompileJobClass:
532 case Action::PrecompileJobClass:
533 case Action::PreprocessJobClass:
534 case Action::ExtractAPIJobClass:
535 case Action::AnalyzeJobClass:
536 case Action::MigrateJobClass:
537 case Action::VerifyPCHJobClass:
538 case Action::BackendJobClass:
539 return getClang();
541 case Action::OffloadBundlingJobClass:
542 case Action::OffloadUnbundlingJobClass:
543 return getOffloadBundler();
545 case Action::OffloadPackagerJobClass:
546 return getOffloadPackager();
547 case Action::LinkerWrapperJobClass:
548 return getLinkerWrapper();
551 llvm_unreachable("Invalid tool kind.");
554 static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
555 const ArgList &Args) {
556 const llvm::Triple &Triple = TC.getTriple();
557 bool IsWindows = Triple.isOSWindows();
559 if (TC.isBareMetal())
560 return Triple.getArchName();
562 if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
563 return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
564 ? "armhf"
565 : "arm";
567 // For historic reasons, Android library is using i686 instead of i386.
568 if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
569 return "i686";
571 if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())
572 return "x32";
574 return llvm::Triple::getArchTypeName(TC.getArch());
577 StringRef ToolChain::getOSLibName() const {
578 if (Triple.isOSDarwin())
579 return "darwin";
581 switch (Triple.getOS()) {
582 case llvm::Triple::FreeBSD:
583 return "freebsd";
584 case llvm::Triple::NetBSD:
585 return "netbsd";
586 case llvm::Triple::OpenBSD:
587 return "openbsd";
588 case llvm::Triple::Solaris:
589 return "sunos";
590 case llvm::Triple::AIX:
591 return "aix";
592 default:
593 return getOS();
597 std::string ToolChain::getCompilerRTPath() const {
598 SmallString<128> Path(getDriver().ResourceDir);
599 if (isBareMetal()) {
600 llvm::sys::path::append(Path, "lib", getOSLibName());
601 if (!SelectedMultilibs.empty()) {
602 Path += SelectedMultilibs.back().gccSuffix();
604 } else if (Triple.isOSUnknown()) {
605 llvm::sys::path::append(Path, "lib");
606 } else {
607 llvm::sys::path::append(Path, "lib", getOSLibName());
609 return std::string(Path);
612 std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
613 StringRef Component,
614 FileType Type) const {
615 std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);
616 return llvm::sys::path::filename(CRTAbsolutePath).str();
619 std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
620 StringRef Component,
621 FileType Type,
622 bool AddArch) const {
623 const llvm::Triple &TT = getTriple();
624 bool IsITANMSVCWindows =
625 TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
627 const char *Prefix =
628 IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";
629 const char *Suffix;
630 switch (Type) {
631 case ToolChain::FT_Object:
632 Suffix = IsITANMSVCWindows ? ".obj" : ".o";
633 break;
634 case ToolChain::FT_Static:
635 Suffix = IsITANMSVCWindows ? ".lib" : ".a";
636 break;
637 case ToolChain::FT_Shared:
638 Suffix = TT.isOSWindows()
639 ? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
640 : ".so";
641 break;
644 std::string ArchAndEnv;
645 if (AddArch) {
646 StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
647 const char *Env = TT.isAndroid() ? "-android" : "";
648 ArchAndEnv = ("-" + Arch + Env).str();
650 return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();
653 std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
654 FileType Type) const {
655 // Check for runtime files in the new layout without the architecture first.
656 std::string CRTBasename =
657 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
658 for (const auto &LibPath : getLibraryPaths()) {
659 SmallString<128> P(LibPath);
660 llvm::sys::path::append(P, CRTBasename);
661 if (getVFS().exists(P))
662 return std::string(P);
665 // Fall back to the old expected compiler-rt name if the new one does not
666 // exist.
667 CRTBasename =
668 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
669 SmallString<128> Path(getCompilerRTPath());
670 llvm::sys::path::append(Path, CRTBasename);
671 return std::string(Path);
674 const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
675 StringRef Component,
676 FileType Type) const {
677 return Args.MakeArgString(getCompilerRT(Args, Component, Type));
680 // Android target triples contain a target version. If we don't have libraries
681 // for the exact target version, we should fall back to the next newest version
682 // or a versionless path, if any.
683 std::optional<std::string>
684 ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {
685 llvm::Triple TripleWithoutLevel(getTriple());
686 TripleWithoutLevel.setEnvironmentName("android"); // remove any version number
687 const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();
688 unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();
689 unsigned BestVersion = 0;
691 SmallString<32> TripleDir;
692 bool UsingUnversionedDir = false;
693 std::error_code EC;
694 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;
695 !EC && LI != LE; LI = LI.increment(EC)) {
696 StringRef DirName = llvm::sys::path::filename(LI->path());
697 StringRef DirNameSuffix = DirName;
698 if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {
699 if (DirNameSuffix.empty() && TripleDir.empty()) {
700 TripleDir = DirName;
701 UsingUnversionedDir = true;
702 } else {
703 unsigned Version;
704 if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&
705 Version < TripleVersion) {
706 BestVersion = Version;
707 TripleDir = DirName;
708 UsingUnversionedDir = false;
714 if (TripleDir.empty())
715 return {};
717 SmallString<128> P(BaseDir);
718 llvm::sys::path::append(P, TripleDir);
719 if (UsingUnversionedDir)
720 D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();
721 return std::string(P);
724 std::optional<std::string>
725 ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
726 auto getPathForTriple =
727 [&](const llvm::Triple &Triple) -> std::optional<std::string> {
728 SmallString<128> P(BaseDir);
729 llvm::sys::path::append(P, Triple.str());
730 if (getVFS().exists(P))
731 return std::string(P);
732 return {};
735 if (auto Path = getPathForTriple(getTriple()))
736 return *Path;
738 // When building with per target runtime directories, various ways of naming
739 // the Arm architecture may have been normalised to simply "arm".
740 // For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".
741 // Since an armv8l system can use libraries built for earlier architecture
742 // versions assuming endian and float ABI match.
744 // Original triple: armv8l-unknown-linux-gnueabihf
745 // Runtime triple: arm-unknown-linux-gnueabihf
747 // We do not do this for armeb (big endian) because doing so could make us
748 // select little endian libraries. In addition, all known armeb triples only
749 // use the "armeb" architecture name.
751 // M profile Arm is bare metal and we know they will not be using the per
752 // target runtime directory layout.
753 if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) {
754 llvm::Triple ArmTriple = getTriple();
755 ArmTriple.setArch(Triple::arm);
756 if (auto Path = getPathForTriple(ArmTriple))
757 return *Path;
760 if (getTriple().isAndroid())
761 return getFallbackAndroidTargetPath(BaseDir);
763 return {};
766 std::optional<std::string> ToolChain::getRuntimePath() const {
767 SmallString<128> P(D.ResourceDir);
768 llvm::sys::path::append(P, "lib");
769 return getTargetSubDirPath(P);
772 std::optional<std::string> ToolChain::getStdlibPath() const {
773 SmallString<128> P(D.Dir);
774 llvm::sys::path::append(P, "..", "lib");
775 return getTargetSubDirPath(P);
778 ToolChain::path_list ToolChain::getArchSpecificLibPaths() const {
779 path_list Paths;
781 auto AddPath = [&](const ArrayRef<StringRef> &SS) {
782 SmallString<128> Path(getDriver().ResourceDir);
783 llvm::sys::path::append(Path, "lib");
784 for (auto &S : SS)
785 llvm::sys::path::append(Path, S);
786 Paths.push_back(std::string(Path));
789 AddPath({getTriple().str()});
790 AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())});
791 return Paths;
794 bool ToolChain::needsProfileRT(const ArgList &Args) {
795 if (Args.hasArg(options::OPT_noprofilelib))
796 return false;
798 return Args.hasArg(options::OPT_fprofile_generate) ||
799 Args.hasArg(options::OPT_fprofile_generate_EQ) ||
800 Args.hasArg(options::OPT_fcs_profile_generate) ||
801 Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
802 Args.hasArg(options::OPT_fprofile_instr_generate) ||
803 Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
804 Args.hasArg(options::OPT_fcreate_profile) ||
805 Args.hasArg(options::OPT_forder_file_instrumentation);
808 bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
809 return Args.hasArg(options::OPT_coverage) ||
810 Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
811 false);
814 Tool *ToolChain::SelectTool(const JobAction &JA) const {
815 if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
816 if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
817 Action::ActionClass AC = JA.getKind();
818 if (AC == Action::AssembleJobClass && useIntegratedAs() &&
819 !getTriple().isOSAIX())
820 return getClangAs();
821 return getTool(AC);
824 std::string ToolChain::GetFilePath(const char *Name) const {
825 return D.GetFilePath(Name, *this);
828 std::string ToolChain::GetProgramPath(const char *Name) const {
829 return D.GetProgramPath(Name, *this);
832 std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
833 if (LinkerIsLLD)
834 *LinkerIsLLD = false;
836 // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
837 // considered as the linker flavor, e.g. "bfd", "gold", or "lld".
838 const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
839 StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
841 // --ld-path= takes precedence over -fuse-ld= and specifies the executable
842 // name. -B, COMPILER_PATH and PATH and consulted if the value does not
843 // contain a path component separator.
844 // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
845 // that --ld-path= points to is lld.
846 if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
847 std::string Path(A->getValue());
848 if (!Path.empty()) {
849 if (llvm::sys::path::parent_path(Path).empty())
850 Path = GetProgramPath(A->getValue());
851 if (llvm::sys::fs::can_execute(Path)) {
852 if (LinkerIsLLD)
853 *LinkerIsLLD = UseLinker == "lld";
854 return std::string(Path);
857 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
858 return GetProgramPath(getDefaultLinker());
860 // If we're passed -fuse-ld= with no argument, or with the argument ld,
861 // then use whatever the default system linker is.
862 if (UseLinker.empty() || UseLinker == "ld") {
863 const char *DefaultLinker = getDefaultLinker();
864 if (llvm::sys::path::is_absolute(DefaultLinker))
865 return std::string(DefaultLinker);
866 else
867 return GetProgramPath(DefaultLinker);
870 // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking
871 // for the linker flavor is brittle. In addition, prepending "ld." or "ld64."
872 // to a relative path is surprising. This is more complex due to priorities
873 // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.
874 if (UseLinker.contains('/'))
875 getDriver().Diag(diag::warn_drv_fuse_ld_path);
877 if (llvm::sys::path::is_absolute(UseLinker)) {
878 // If we're passed what looks like an absolute path, don't attempt to
879 // second-guess that.
880 if (llvm::sys::fs::can_execute(UseLinker))
881 return std::string(UseLinker);
882 } else {
883 llvm::SmallString<8> LinkerName;
884 if (Triple.isOSDarwin())
885 LinkerName.append("ld64.");
886 else
887 LinkerName.append("ld.");
888 LinkerName.append(UseLinker);
890 std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
891 if (llvm::sys::fs::can_execute(LinkerPath)) {
892 if (LinkerIsLLD)
893 *LinkerIsLLD = UseLinker == "lld";
894 return LinkerPath;
898 if (A)
899 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
901 return GetProgramPath(getDefaultLinker());
904 std::string ToolChain::GetStaticLibToolPath() const {
905 // TODO: Add support for static lib archiving on Windows
906 if (Triple.isOSDarwin())
907 return GetProgramPath("libtool");
908 return GetProgramPath("llvm-ar");
911 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
912 types::ID id = types::lookupTypeForExtension(Ext);
914 // Flang always runs the preprocessor and has no notion of "preprocessed
915 // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
916 // them differently.
917 if (D.IsFlangMode() && id == types::TY_PP_Fortran)
918 id = types::TY_Fortran;
920 return id;
923 bool ToolChain::HasNativeLLVMSupport() const {
924 return false;
927 bool ToolChain::isCrossCompiling() const {
928 llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
929 switch (HostTriple.getArch()) {
930 // The A32/T32/T16 instruction sets are not separate architectures in this
931 // context.
932 case llvm::Triple::arm:
933 case llvm::Triple::armeb:
934 case llvm::Triple::thumb:
935 case llvm::Triple::thumbeb:
936 return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
937 getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
938 default:
939 return HostTriple.getArch() != getArch();
943 ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
944 return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
945 VersionTuple());
948 llvm::ExceptionHandling
949 ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
950 return llvm::ExceptionHandling::None;
953 bool ToolChain::isThreadModelSupported(const StringRef Model) const {
954 if (Model == "single") {
955 // FIXME: 'single' is only supported on ARM and WebAssembly so far.
956 return Triple.getArch() == llvm::Triple::arm ||
957 Triple.getArch() == llvm::Triple::armeb ||
958 Triple.getArch() == llvm::Triple::thumb ||
959 Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm();
960 } else if (Model == "posix")
961 return true;
963 return false;
966 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
967 types::ID InputType) const {
968 switch (getTriple().getArch()) {
969 default:
970 return getTripleString();
972 case llvm::Triple::x86_64: {
973 llvm::Triple Triple = getTriple();
974 if (!Triple.isOSBinFormatMachO())
975 return getTripleString();
977 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
978 // x86_64h goes in the triple. Other -march options just use the
979 // vanilla triple we already have.
980 StringRef MArch = A->getValue();
981 if (MArch == "x86_64h")
982 Triple.setArchName(MArch);
984 return Triple.getTriple();
986 case llvm::Triple::aarch64: {
987 llvm::Triple Triple = getTriple();
988 if (!Triple.isOSBinFormatMachO())
989 return getTripleString();
991 if (Triple.isArm64e())
992 return getTripleString();
994 // FIXME: older versions of ld64 expect the "arm64" component in the actual
995 // triple string and query it to determine whether an LTO file can be
996 // handled. Remove this when we don't care any more.
997 Triple.setArchName("arm64");
998 return Triple.getTriple();
1000 case llvm::Triple::aarch64_32:
1001 return getTripleString();
1002 case llvm::Triple::arm:
1003 case llvm::Triple::armeb:
1004 case llvm::Triple::thumb:
1005 case llvm::Triple::thumbeb: {
1006 llvm::Triple Triple = getTriple();
1007 tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);
1008 tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);
1009 return Triple.getTriple();
1014 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1015 types::ID InputType) const {
1016 return ComputeLLVMTriple(Args, InputType);
1019 std::string ToolChain::computeSysRoot() const {
1020 return D.SysRoot;
1023 void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1024 ArgStringList &CC1Args) const {
1025 // Each toolchain should provide the appropriate include flags.
1028 void ToolChain::addClangTargetOptions(
1029 const ArgList &DriverArgs, ArgStringList &CC1Args,
1030 Action::OffloadKind DeviceOffloadKind) const {}
1032 void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
1033 ArgStringList &CC1ASArgs) const {}
1035 void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
1037 void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
1038 llvm::opt::ArgStringList &CmdArgs) const {
1039 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1040 return;
1042 CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
1045 ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
1046 const ArgList &Args) const {
1047 if (runtimeLibType)
1048 return *runtimeLibType;
1050 const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
1051 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
1053 // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
1054 if (LibName == "compiler-rt")
1055 runtimeLibType = ToolChain::RLT_CompilerRT;
1056 else if (LibName == "libgcc")
1057 runtimeLibType = ToolChain::RLT_Libgcc;
1058 else if (LibName == "platform")
1059 runtimeLibType = GetDefaultRuntimeLibType();
1060 else {
1061 if (A)
1062 getDriver().Diag(diag::err_drv_invalid_rtlib_name)
1063 << A->getAsString(Args);
1065 runtimeLibType = GetDefaultRuntimeLibType();
1068 return *runtimeLibType;
1071 ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
1072 const ArgList &Args) const {
1073 if (unwindLibType)
1074 return *unwindLibType;
1076 const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
1077 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;
1079 if (LibName == "none")
1080 unwindLibType = ToolChain::UNW_None;
1081 else if (LibName == "platform" || LibName == "") {
1082 ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
1083 if (RtLibType == ToolChain::RLT_CompilerRT) {
1084 if (getTriple().isAndroid() || getTriple().isOSAIX())
1085 unwindLibType = ToolChain::UNW_CompilerRT;
1086 else
1087 unwindLibType = ToolChain::UNW_None;
1088 } else if (RtLibType == ToolChain::RLT_Libgcc)
1089 unwindLibType = ToolChain::UNW_Libgcc;
1090 } else if (LibName == "libunwind") {
1091 if (GetRuntimeLibType(Args) == RLT_Libgcc)
1092 getDriver().Diag(diag::err_drv_incompatible_unwindlib);
1093 unwindLibType = ToolChain::UNW_CompilerRT;
1094 } else if (LibName == "libgcc")
1095 unwindLibType = ToolChain::UNW_Libgcc;
1096 else {
1097 if (A)
1098 getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
1099 << A->getAsString(Args);
1101 unwindLibType = GetDefaultUnwindLibType();
1104 return *unwindLibType;
1107 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
1108 if (cxxStdlibType)
1109 return *cxxStdlibType;
1111 const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
1112 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
1114 // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
1115 if (LibName == "libc++")
1116 cxxStdlibType = ToolChain::CST_Libcxx;
1117 else if (LibName == "libstdc++")
1118 cxxStdlibType = ToolChain::CST_Libstdcxx;
1119 else if (LibName == "platform")
1120 cxxStdlibType = GetDefaultCXXStdlibType();
1121 else {
1122 if (A)
1123 getDriver().Diag(diag::err_drv_invalid_stdlib_name)
1124 << A->getAsString(Args);
1126 cxxStdlibType = GetDefaultCXXStdlibType();
1129 return *cxxStdlibType;
1132 /// Utility function to add a system include directory to CC1 arguments.
1133 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
1134 ArgStringList &CC1Args,
1135 const Twine &Path) {
1136 CC1Args.push_back("-internal-isystem");
1137 CC1Args.push_back(DriverArgs.MakeArgString(Path));
1140 /// Utility function to add a system include directory with extern "C"
1141 /// semantics to CC1 arguments.
1143 /// Note that this should be used rarely, and only for directories that
1144 /// historically and for legacy reasons are treated as having implicit extern
1145 /// "C" semantics. These semantics are *ignored* by and large today, but its
1146 /// important to preserve the preprocessor changes resulting from the
1147 /// classification.
1148 /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
1149 ArgStringList &CC1Args,
1150 const Twine &Path) {
1151 CC1Args.push_back("-internal-externc-isystem");
1152 CC1Args.push_back(DriverArgs.MakeArgString(Path));
1155 void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
1156 ArgStringList &CC1Args,
1157 const Twine &Path) {
1158 if (llvm::sys::fs::exists(Path))
1159 addExternCSystemInclude(DriverArgs, CC1Args, Path);
1162 /// Utility function to add a list of system include directories to CC1.
1163 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
1164 ArgStringList &CC1Args,
1165 ArrayRef<StringRef> Paths) {
1166 for (const auto &Path : Paths) {
1167 CC1Args.push_back("-internal-isystem");
1168 CC1Args.push_back(DriverArgs.MakeArgString(Path));
1172 /*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
1173 const Twine &B, const Twine &C,
1174 const Twine &D) {
1175 SmallString<128> Result(Path);
1176 llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
1177 return std::string(Result);
1180 std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
1181 std::error_code EC;
1182 int MaxVersion = 0;
1183 std::string MaxVersionString;
1184 SmallString<128> Path(IncludePath);
1185 llvm::sys::path::append(Path, "c++");
1186 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
1187 !EC && LI != LE; LI = LI.increment(EC)) {
1188 StringRef VersionText = llvm::sys::path::filename(LI->path());
1189 int Version;
1190 if (VersionText[0] == 'v' &&
1191 !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
1192 if (Version > MaxVersion) {
1193 MaxVersion = Version;
1194 MaxVersionString = std::string(VersionText);
1198 if (!MaxVersion)
1199 return "";
1200 return MaxVersionString;
1203 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1204 ArgStringList &CC1Args) const {
1205 // Header search paths should be handled by each of the subclasses.
1206 // Historically, they have not been, and instead have been handled inside of
1207 // the CC1-layer frontend. As the logic is hoisted out, this generic function
1208 // will slowly stop being called.
1210 // While it is being called, replicate a bit of a hack to propagate the
1211 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
1212 // header search paths with it. Once all systems are overriding this
1213 // function, the CC1 flag and this line can be removed.
1214 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
1217 void ToolChain::AddClangCXXStdlibIsystemArgs(
1218 const llvm::opt::ArgList &DriverArgs,
1219 llvm::opt::ArgStringList &CC1Args) const {
1220 DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
1221 // This intentionally only looks at -nostdinc++, and not -nostdinc or
1222 // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain
1223 // setups with non-standard search logic for the C++ headers, while still
1224 // allowing users of the toolchain to bring their own C++ headers. Such a
1225 // toolchain likely also has non-standard search logic for the C headers and
1226 // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should
1227 // still work in that case and only be suppressed by an explicit -nostdinc++
1228 // in a project using the toolchain.
1229 if (!DriverArgs.hasArg(options::OPT_nostdincxx))
1230 for (const auto &P :
1231 DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
1232 addSystemInclude(DriverArgs, CC1Args, P);
1235 bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {
1236 return getDriver().CCCIsCXX() &&
1237 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
1238 options::OPT_nostdlibxx);
1241 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
1242 ArgStringList &CmdArgs) const {
1243 assert(!Args.hasArg(options::OPT_nostdlibxx) &&
1244 "should not have called this");
1245 CXXStdlibType Type = GetCXXStdlibType(Args);
1247 switch (Type) {
1248 case ToolChain::CST_Libcxx:
1249 CmdArgs.push_back("-lc++");
1250 if (Args.hasArg(options::OPT_fexperimental_library))
1251 CmdArgs.push_back("-lc++experimental");
1252 break;
1254 case ToolChain::CST_Libstdcxx:
1255 CmdArgs.push_back("-lstdc++");
1256 break;
1260 void ToolChain::AddFilePathLibArgs(const ArgList &Args,
1261 ArgStringList &CmdArgs) const {
1262 for (const auto &LibPath : getFilePaths())
1263 if(LibPath.length() > 0)
1264 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
1267 void ToolChain::AddCCKextLibArgs(const ArgList &Args,
1268 ArgStringList &CmdArgs) const {
1269 CmdArgs.push_back("-lcc_kext");
1272 bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
1273 std::string &Path) const {
1274 // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
1275 // (to keep the linker options consistent with gcc and clang itself).
1276 if (!isOptimizationLevelFast(Args)) {
1277 // Check if -ffast-math or -funsafe-math.
1278 Arg *A =
1279 Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
1280 options::OPT_funsafe_math_optimizations,
1281 options::OPT_fno_unsafe_math_optimizations);
1283 if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
1284 A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
1285 return false;
1287 // If crtfastmath.o exists add it to the arguments.
1288 Path = GetFilePath("crtfastmath.o");
1289 return (Path != "crtfastmath.o"); // Not found.
1292 bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
1293 ArgStringList &CmdArgs) const {
1294 std::string Path;
1295 if (isFastMathRuntimeAvailable(Args, Path)) {
1296 CmdArgs.push_back(Args.MakeArgString(Path));
1297 return true;
1300 return false;
1303 Expected<SmallVector<std::string>>
1304 ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
1305 return SmallVector<std::string>();
1308 SanitizerMask ToolChain::getSupportedSanitizers() const {
1309 // Return sanitizers which don't require runtime support and are not
1310 // platform dependent.
1312 SanitizerMask Res =
1313 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
1314 (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
1315 SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
1316 SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
1317 SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
1318 SanitizerKind::Nullability | SanitizerKind::LocalBounds;
1319 if (getTriple().getArch() == llvm::Triple::x86 ||
1320 getTriple().getArch() == llvm::Triple::x86_64 ||
1321 getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||
1322 getTriple().isAArch64() || getTriple().isRISCV() ||
1323 getTriple().isLoongArch64())
1324 Res |= SanitizerKind::CFIICall;
1325 if (getTriple().getArch() == llvm::Triple::x86_64 ||
1326 getTriple().isAArch64(64) || getTriple().isRISCV())
1327 Res |= SanitizerKind::ShadowCallStack;
1328 if (getTriple().isAArch64(64))
1329 Res |= SanitizerKind::MemTag;
1330 return Res;
1333 void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
1334 ArgStringList &CC1Args) const {}
1336 void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
1337 ArgStringList &CC1Args) const {}
1339 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
1340 ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
1341 return {};
1344 void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
1345 ArgStringList &CC1Args) const {}
1347 static VersionTuple separateMSVCFullVersion(unsigned Version) {
1348 if (Version < 100)
1349 return VersionTuple(Version);
1351 if (Version < 10000)
1352 return VersionTuple(Version / 100, Version % 100);
1354 unsigned Build = 0, Factor = 1;
1355 for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
1356 Build = Build + (Version % 10) * Factor;
1357 return VersionTuple(Version / 100, Version % 100, Build);
1360 VersionTuple
1361 ToolChain::computeMSVCVersion(const Driver *D,
1362 const llvm::opt::ArgList &Args) const {
1363 const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
1364 const Arg *MSCompatibilityVersion =
1365 Args.getLastArg(options::OPT_fms_compatibility_version);
1367 if (MSCVersion && MSCompatibilityVersion) {
1368 if (D)
1369 D->Diag(diag::err_drv_argument_not_allowed_with)
1370 << MSCVersion->getAsString(Args)
1371 << MSCompatibilityVersion->getAsString(Args);
1372 return VersionTuple();
1375 if (MSCompatibilityVersion) {
1376 VersionTuple MSVT;
1377 if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {
1378 if (D)
1379 D->Diag(diag::err_drv_invalid_value)
1380 << MSCompatibilityVersion->getAsString(Args)
1381 << MSCompatibilityVersion->getValue();
1382 } else {
1383 return MSVT;
1387 if (MSCVersion) {
1388 unsigned Version = 0;
1389 if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {
1390 if (D)
1391 D->Diag(diag::err_drv_invalid_value)
1392 << MSCVersion->getAsString(Args) << MSCVersion->getValue();
1393 } else {
1394 return separateMSVCFullVersion(Version);
1398 return VersionTuple();
1401 llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
1402 const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
1403 SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {
1404 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1405 const OptTable &Opts = getDriver().getOpts();
1406 bool Modified = false;
1408 // Handle -Xopenmp-target flags
1409 for (auto *A : Args) {
1410 // Exclude flags which may only apply to the host toolchain.
1411 // Do not exclude flags when the host triple (AuxTriple)
1412 // matches the current toolchain triple. If it is not present
1413 // at all, target and host share a toolchain.
1414 if (A->getOption().matches(options::OPT_m_Group)) {
1415 // Pass code object version to device toolchain
1416 // to correctly set metadata in intermediate files.
1417 if (SameTripleAsHost ||
1418 A->getOption().matches(options::OPT_mcode_object_version_EQ))
1419 DAL->append(A);
1420 else
1421 Modified = true;
1422 continue;
1425 unsigned Index;
1426 unsigned Prev;
1427 bool XOpenMPTargetNoTriple =
1428 A->getOption().matches(options::OPT_Xopenmp_target);
1430 if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
1431 llvm::Triple TT(getOpenMPTriple(A->getValue(0)));
1433 // Passing device args: -Xopenmp-target=<triple> -opt=val.
1434 if (TT.getTriple() == getTripleString())
1435 Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
1436 else
1437 continue;
1438 } else if (XOpenMPTargetNoTriple) {
1439 // Passing device args: -Xopenmp-target -opt=val.
1440 Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
1441 } else {
1442 DAL->append(A);
1443 continue;
1446 // Parse the argument to -Xopenmp-target.
1447 Prev = Index;
1448 std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
1449 if (!XOpenMPTargetArg || Index > Prev + 1) {
1450 getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
1451 << A->getAsString(Args);
1452 continue;
1454 if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
1455 Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
1456 getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
1457 continue;
1459 XOpenMPTargetArg->setBaseArg(A);
1460 A = XOpenMPTargetArg.release();
1461 AllocatedArgs.push_back(A);
1462 DAL->append(A);
1463 Modified = true;
1466 if (Modified)
1467 return DAL;
1469 delete DAL;
1470 return nullptr;
1473 // TODO: Currently argument values separated by space e.g.
1474 // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be
1475 // fixed.
1476 void ToolChain::TranslateXarchArgs(
1477 const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,
1478 llvm::opt::DerivedArgList *DAL,
1479 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1480 const OptTable &Opts = getDriver().getOpts();
1481 unsigned ValuePos = 1;
1482 if (A->getOption().matches(options::OPT_Xarch_device) ||
1483 A->getOption().matches(options::OPT_Xarch_host))
1484 ValuePos = 0;
1486 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));
1487 unsigned Prev = Index;
1488 std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));
1490 // If the argument parsing failed or more than one argument was
1491 // consumed, the -Xarch_ argument's parameter tried to consume
1492 // extra arguments. Emit an error and ignore.
1494 // We also want to disallow any options which would alter the
1495 // driver behavior; that isn't going to work in our model. We
1496 // use options::NoXarchOption to control this.
1497 if (!XarchArg || Index > Prev + 1) {
1498 getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
1499 << A->getAsString(Args);
1500 return;
1501 } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) {
1502 auto &Diags = getDriver().getDiags();
1503 unsigned DiagID =
1504 Diags.getCustomDiagID(DiagnosticsEngine::Error,
1505 "invalid Xarch argument: '%0', not all driver "
1506 "options can be forwared via Xarch argument");
1507 Diags.Report(DiagID) << A->getAsString(Args);
1508 return;
1510 XarchArg->setBaseArg(A);
1511 A = XarchArg.release();
1512 if (!AllocatedArgs)
1513 DAL->AddSynthesizedArg(A);
1514 else
1515 AllocatedArgs->push_back(A);
1518 llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
1519 const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
1520 Action::OffloadKind OFK,
1521 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1522 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1523 bool Modified = false;
1525 bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;
1526 for (Arg *A : Args) {
1527 bool NeedTrans = false;
1528 bool Skip = false;
1529 if (A->getOption().matches(options::OPT_Xarch_device)) {
1530 NeedTrans = IsDevice;
1531 Skip = !IsDevice;
1532 } else if (A->getOption().matches(options::OPT_Xarch_host)) {
1533 NeedTrans = !IsDevice;
1534 Skip = IsDevice;
1535 } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {
1536 // Do not translate -Xarch_ options for non CUDA/HIP toolchain since
1537 // they may need special translation.
1538 // Skip this argument unless the architecture matches BoundArch
1539 if (BoundArch.empty() || A->getValue(0) != BoundArch)
1540 Skip = true;
1541 else
1542 NeedTrans = true;
1544 if (NeedTrans || Skip)
1545 Modified = true;
1546 if (NeedTrans)
1547 TranslateXarchArgs(Args, A, DAL, AllocatedArgs);
1548 if (!Skip)
1549 DAL->append(A);
1552 if (Modified)
1553 return DAL;
1555 delete DAL;
1556 return nullptr;