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/ARM.h"
11 #include "ToolChains/Clang.h"
12 #include "ToolChains/Flang.h"
13 #include "ToolChains/InterfaceStubs.h"
14 #include "clang/Basic/ObjCRuntime.h"
15 #include "clang/Basic/Sanitizers.h"
16 #include "clang/Config/config.h"
17 #include "clang/Driver/Action.h"
18 #include "clang/Driver/Driver.h"
19 #include "clang/Driver/DriverDiagnostic.h"
20 #include "clang/Driver/InputInfo.h"
21 #include "clang/Driver/Job.h"
22 #include "clang/Driver/Options.h"
23 #include "clang/Driver/SanitizerArgs.h"
24 #include "clang/Driver/XRayArgs.h"
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/ADT/Triple.h"
29 #include "llvm/ADT/Twine.h"
30 #include "llvm/Config/llvm-config.h"
31 #include "llvm/MC/MCTargetOptions.h"
32 #include "llvm/MC/TargetRegistry.h"
33 #include "llvm/Option/Arg.h"
34 #include "llvm/Option/ArgList.h"
35 #include "llvm/Option/OptTable.h"
36 #include "llvm/Option/Option.h"
37 #include "llvm/Support/ErrorHandling.h"
38 #include "llvm/Support/FileSystem.h"
39 #include "llvm/Support/FileUtilities.h"
40 #include "llvm/Support/Path.h"
41 #include "llvm/Support/TargetParser.h"
42 #include "llvm/Support/VersionTuple.h"
43 #include "llvm/Support/VirtualFileSystem.h"
44 #include <cassert>
45 #include <cstddef>
46 #include <cstring>
47 #include <string>
48
49 using namespace clang;
50 using namespace driver;
51 using namespace tools;
52 using namespace llvm;
53 using namespace llvm::opt;
54
GetRTTIArgument(const ArgList & Args)55 static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
56 return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
57 options::OPT_fno_rtti, options::OPT_frtti);
58 }
59
CalculateRTTIMode(const ArgList & Args,const llvm::Triple & Triple,const Arg * CachedRTTIArg)60 static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
61 const llvm::Triple &Triple,
62 const Arg *CachedRTTIArg) {
63 // Explicit rtti/no-rtti args
64 if (CachedRTTIArg) {
65 if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
66 return ToolChain::RM_Enabled;
67 else
68 return ToolChain::RM_Disabled;
69 }
70
71 // -frtti is default, except for the PS4/PS5 and DriverKit.
72 bool NoRTTI = Triple.isPS() || Triple.isDriverKit();
73 return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
74 }
75
ToolChain(const Driver & D,const llvm::Triple & T,const ArgList & Args)76 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
77 const ArgList &Args)
78 : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
79 CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
80 auto addIfExists = [this](path_list &List, const std::string &Path) {
81 if (getVFS().exists(Path))
82 List.push_back(Path);
83 };
84
85 for (const auto &Path : getRuntimePaths())
86 addIfExists(getLibraryPaths(), Path);
87 for (const auto &Path : getStdlibPaths())
88 addIfExists(getFilePaths(), Path);
89 addIfExists(getFilePaths(), getArchSpecificLibPath());
90 }
91
92 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
executeToolChainProgram(StringRef Executable) const93 ToolChain::executeToolChainProgram(StringRef Executable) const {
94 llvm::SmallString<64> OutputFile;
95 llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
96 llvm::FileRemover OutputRemover(OutputFile.c_str());
97 std::optional<llvm::StringRef> Redirects[] = {
98 {""},
99 OutputFile.str(),
100 {""},
101 };
102
103 std::string ErrorMessage;
104 if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects,
105 /* SecondsToWait */ 0,
106 /*MemoryLimit*/ 0, &ErrorMessage))
107 return llvm::createStringError(std::error_code(),
108 Executable + ": " + ErrorMessage);
109
110 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
111 llvm::MemoryBuffer::getFile(OutputFile.c_str());
112 if (!OutputBuf)
113 return llvm::createStringError(OutputBuf.getError(),
114 "Failed to read stdout of " + Executable +
115 ": " + OutputBuf.getError().message());
116 return std::move(*OutputBuf);
117 }
118
setTripleEnvironment(llvm::Triple::EnvironmentType Env)119 void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
120 Triple.setEnvironment(Env);
121 if (EffectiveTriple != llvm::Triple())
122 EffectiveTriple.setEnvironment(Env);
123 }
124
125 ToolChain::~ToolChain() = default;
126
getVFS() const127 llvm::vfs::FileSystem &ToolChain::getVFS() const {
128 return getDriver().getVFS();
129 }
130
useIntegratedAs() const131 bool ToolChain::useIntegratedAs() const {
132 return Args.hasFlag(options::OPT_fintegrated_as,
133 options::OPT_fno_integrated_as,
134 IsIntegratedAssemblerDefault());
135 }
136
useIntegratedBackend() const137 bool ToolChain::useIntegratedBackend() const {
138 assert(
139 ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||
140 (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&
141 "(Non-)integrated backend set incorrectly!");
142
143 bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,
144 options::OPT_fno_integrated_objemitter,
145 IsIntegratedBackendDefault());
146
147 // Diagnose when integrated-objemitter options are not supported by this
148 // toolchain.
149 unsigned DiagID;
150 if ((IBackend && !IsIntegratedBackendSupported()) ||
151 (!IBackend && !IsNonIntegratedBackendSupported()))
152 DiagID = clang::diag::err_drv_unsupported_opt_for_target;
153 else
154 DiagID = clang::diag::warn_drv_unsupported_opt_for_target;
155 Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);
156 if (A && !IsNonIntegratedBackendSupported())
157 D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
158 A = Args.getLastArg(options::OPT_fintegrated_objemitter);
159 if (A && !IsIntegratedBackendSupported())
160 D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
161
162 return IBackend;
163 }
164
useRelaxRelocations() const165 bool ToolChain::useRelaxRelocations() const {
166 return ENABLE_X86_RELAX_RELOCATIONS;
167 }
168
defaultToIEEELongDouble() const169 bool ToolChain::defaultToIEEELongDouble() const {
170 return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
171 }
172
173 SanitizerArgs
getSanitizerArgs(const llvm::opt::ArgList & JobArgs) const174 ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
175 SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
176 SanitizerArgsChecked = true;
177 return SanArgs;
178 }
179
getXRayArgs() const180 const XRayArgs& ToolChain::getXRayArgs() const {
181 if (!XRayArguments)
182 XRayArguments.reset(new XRayArgs(*this, Args));
183 return *XRayArguments;
184 }
185
186 namespace {
187
188 struct DriverSuffix {
189 const char *Suffix;
190 const char *ModeFlag;
191 };
192
193 } // namespace
194
FindDriverSuffix(StringRef ProgName,size_t & Pos)195 static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
196 // A list of known driver suffixes. Suffixes are compared against the
197 // program name in order. If there is a match, the frontend type is updated as
198 // necessary by applying the ModeFlag.
199 static const DriverSuffix DriverSuffixes[] = {
200 {"clang", nullptr},
201 {"clang++", "--driver-mode=g++"},
202 {"clang-c++", "--driver-mode=g++"},
203 {"clang-cc", nullptr},
204 {"clang-cpp", "--driver-mode=cpp"},
205 {"clang-g++", "--driver-mode=g++"},
206 {"clang-gcc", nullptr},
207 {"clang-cl", "--driver-mode=cl"},
208 {"cc", nullptr},
209 {"cpp", "--driver-mode=cpp"},
210 {"cl", "--driver-mode=cl"},
211 {"++", "--driver-mode=g++"},
212 {"flang", "--driver-mode=flang"},
213 {"clang-dxc", "--driver-mode=dxc"},
214 };
215
216 for (const auto &DS : DriverSuffixes) {
217 StringRef Suffix(DS.Suffix);
218 if (ProgName.endswith(Suffix)) {
219 Pos = ProgName.size() - Suffix.size();
220 return &DS;
221 }
222 }
223 return nullptr;
224 }
225
226 /// Normalize the program name from argv[0] by stripping the file extension if
227 /// present and lower-casing the string on Windows.
normalizeProgramName(llvm::StringRef Argv0)228 static std::string normalizeProgramName(llvm::StringRef Argv0) {
229 std::string ProgName = std::string(llvm::sys::path::filename(Argv0));
230 if (is_style_windows(llvm::sys::path::Style::native)) {
231 // Transform to lowercase for case insensitive file systems.
232 std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
233 ::tolower);
234 }
235 return ProgName;
236 }
237
parseDriverSuffix(StringRef ProgName,size_t & Pos)238 static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
239 // Try to infer frontend type and default target from the program name by
240 // comparing it against DriverSuffixes in order.
241
242 // If there is a match, the function tries to identify a target as prefix.
243 // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
244 // prefix "x86_64-linux". If such a target prefix is found, it may be
245 // added via -target as implicit first argument.
246 const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
247
248 if (!DS && ProgName.endswith(".exe")) {
249 // Try again after stripping the executable suffix:
250 // clang++.exe -> clang++
251 ProgName = ProgName.drop_back(StringRef(".exe").size());
252 DS = FindDriverSuffix(ProgName, Pos);
253 }
254
255 if (!DS) {
256 // Try again after stripping any trailing version number:
257 // clang++3.5 -> clang++
258 ProgName = ProgName.rtrim("0123456789.");
259 DS = FindDriverSuffix(ProgName, Pos);
260 }
261
262 if (!DS) {
263 // Try again after stripping trailing -component.
264 // clang++-tot -> clang++
265 ProgName = ProgName.slice(0, ProgName.rfind('-'));
266 DS = FindDriverSuffix(ProgName, Pos);
267 }
268 return DS;
269 }
270
271 ParsedClangName
getTargetAndModeFromProgramName(StringRef PN)272 ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
273 std::string ProgName = normalizeProgramName(PN);
274 size_t SuffixPos;
275 const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
276 if (!DS)
277 return {};
278 size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
279
280 size_t LastComponent = ProgName.rfind('-', SuffixPos);
281 if (LastComponent == std::string::npos)
282 return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
283 std::string ModeSuffix = ProgName.substr(LastComponent + 1,
284 SuffixEnd - LastComponent - 1);
285
286 // Infer target from the prefix.
287 StringRef Prefix(ProgName);
288 Prefix = Prefix.slice(0, LastComponent);
289 std::string IgnoredError;
290 bool IsRegistered =
291 llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);
292 return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,
293 IsRegistered};
294 }
295
getDefaultUniversalArchName() const296 StringRef ToolChain::getDefaultUniversalArchName() const {
297 // In universal driver terms, the arch name accepted by -arch isn't exactly
298 // the same as the ones that appear in the triple. Roughly speaking, this is
299 // an inverse of the darwin::getArchTypeForDarwinArchName() function.
300 switch (Triple.getArch()) {
301 case llvm::Triple::aarch64: {
302 if (getTriple().isArm64e())
303 return "arm64e";
304 return "arm64";
305 }
306 case llvm::Triple::aarch64_32:
307 return "arm64_32";
308 case llvm::Triple::ppc:
309 return "ppc";
310 case llvm::Triple::ppcle:
311 return "ppcle";
312 case llvm::Triple::ppc64:
313 return "ppc64";
314 case llvm::Triple::ppc64le:
315 return "ppc64le";
316 default:
317 return Triple.getArchName();
318 }
319 }
320
getInputFilename(const InputInfo & Input) const321 std::string ToolChain::getInputFilename(const InputInfo &Input) const {
322 return Input.getFilename();
323 }
324
325 ToolChain::UnwindTableLevel
getDefaultUnwindTableLevel(const ArgList & Args) const326 ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
327 return UnwindTableLevel::None;
328 }
329
getClang() const330 Tool *ToolChain::getClang() const {
331 if (!Clang)
332 Clang.reset(new tools::Clang(*this, useIntegratedBackend()));
333 return Clang.get();
334 }
335
getFlang() const336 Tool *ToolChain::getFlang() const {
337 if (!Flang)
338 Flang.reset(new tools::Flang(*this));
339 return Flang.get();
340 }
341
buildAssembler() const342 Tool *ToolChain::buildAssembler() const {
343 return new tools::ClangAs(*this);
344 }
345
buildLinker() const346 Tool *ToolChain::buildLinker() const {
347 llvm_unreachable("Linking is not supported by this toolchain");
348 }
349
buildStaticLibTool() const350 Tool *ToolChain::buildStaticLibTool() const {
351 llvm_unreachable("Creating static lib is not supported by this toolchain");
352 }
353
getAssemble() const354 Tool *ToolChain::getAssemble() const {
355 if (!Assemble)
356 Assemble.reset(buildAssembler());
357 return Assemble.get();
358 }
359
getClangAs() const360 Tool *ToolChain::getClangAs() const {
361 if (!Assemble)
362 Assemble.reset(new tools::ClangAs(*this));
363 return Assemble.get();
364 }
365
getLink() const366 Tool *ToolChain::getLink() const {
367 if (!Link)
368 Link.reset(buildLinker());
369 return Link.get();
370 }
371
getStaticLibTool() const372 Tool *ToolChain::getStaticLibTool() const {
373 if (!StaticLibTool)
374 StaticLibTool.reset(buildStaticLibTool());
375 return StaticLibTool.get();
376 }
377
getIfsMerge() const378 Tool *ToolChain::getIfsMerge() const {
379 if (!IfsMerge)
380 IfsMerge.reset(new tools::ifstool::Merger(*this));
381 return IfsMerge.get();
382 }
383
getOffloadBundler() const384 Tool *ToolChain::getOffloadBundler() const {
385 if (!OffloadBundler)
386 OffloadBundler.reset(new tools::OffloadBundler(*this));
387 return OffloadBundler.get();
388 }
389
getOffloadPackager() const390 Tool *ToolChain::getOffloadPackager() const {
391 if (!OffloadPackager)
392 OffloadPackager.reset(new tools::OffloadPackager(*this));
393 return OffloadPackager.get();
394 }
395
getLinkerWrapper() const396 Tool *ToolChain::getLinkerWrapper() const {
397 if (!LinkerWrapper)
398 LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
399 return LinkerWrapper.get();
400 }
401
getTool(Action::ActionClass AC) const402 Tool *ToolChain::getTool(Action::ActionClass AC) const {
403 switch (AC) {
404 case Action::AssembleJobClass:
405 return getAssemble();
406
407 case Action::IfsMergeJobClass:
408 return getIfsMerge();
409
410 case Action::LinkJobClass:
411 return getLink();
412
413 case Action::StaticLibJobClass:
414 return getStaticLibTool();
415
416 case Action::InputClass:
417 case Action::BindArchClass:
418 case Action::OffloadClass:
419 case Action::LipoJobClass:
420 case Action::DsymutilJobClass:
421 case Action::VerifyDebugInfoJobClass:
422 llvm_unreachable("Invalid tool kind.");
423
424 case Action::CompileJobClass:
425 case Action::PrecompileJobClass:
426 case Action::PreprocessJobClass:
427 case Action::ExtractAPIJobClass:
428 case Action::AnalyzeJobClass:
429 case Action::MigrateJobClass:
430 case Action::VerifyPCHJobClass:
431 case Action::BackendJobClass:
432 return getClang();
433
434 case Action::OffloadBundlingJobClass:
435 case Action::OffloadUnbundlingJobClass:
436 return getOffloadBundler();
437
438 case Action::OffloadPackagerJobClass:
439 return getOffloadPackager();
440 case Action::LinkerWrapperJobClass:
441 return getLinkerWrapper();
442 }
443
444 llvm_unreachable("Invalid tool kind.");
445 }
446
getArchNameForCompilerRTLib(const ToolChain & TC,const ArgList & Args)447 static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
448 const ArgList &Args) {
449 const llvm::Triple &Triple = TC.getTriple();
450 bool IsWindows = Triple.isOSWindows();
451
452 if (TC.isBareMetal())
453 return Triple.getArchName();
454
455 if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
456 return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
457 ? "armhf"
458 : "arm";
459
460 // For historic reasons, Android library is using i686 instead of i386.
461 if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
462 return "i686";
463
464 if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())
465 return "x32";
466
467 return llvm::Triple::getArchTypeName(TC.getArch());
468 }
469
getOSLibName() const470 StringRef ToolChain::getOSLibName() const {
471 if (Triple.isOSDarwin())
472 return "darwin";
473
474 switch (Triple.getOS()) {
475 case llvm::Triple::FreeBSD:
476 return "freebsd";
477 case llvm::Triple::NetBSD:
478 return "netbsd";
479 case llvm::Triple::OpenBSD:
480 return "openbsd";
481 case llvm::Triple::Solaris:
482 return "sunos";
483 case llvm::Triple::AIX:
484 return "aix";
485 default:
486 return getOS();
487 }
488 }
489
getCompilerRTPath() const490 std::string ToolChain::getCompilerRTPath() const {
491 SmallString<128> Path(getDriver().ResourceDir);
492 if (isBareMetal()) {
493 llvm::sys::path::append(Path, "lib", getOSLibName());
494 Path += SelectedMultilib.gccSuffix();
495 } else if (Triple.isOSUnknown()) {
496 llvm::sys::path::append(Path, "lib");
497 } else {
498 llvm::sys::path::append(Path, "lib", getOSLibName());
499 }
500 return std::string(Path.str());
501 }
502
getCompilerRTBasename(const ArgList & Args,StringRef Component,FileType Type) const503 std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
504 StringRef Component,
505 FileType Type) const {
506 std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);
507 return llvm::sys::path::filename(CRTAbsolutePath).str();
508 }
509
buildCompilerRTBasename(const llvm::opt::ArgList & Args,StringRef Component,FileType Type,bool AddArch) const510 std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
511 StringRef Component,
512 FileType Type,
513 bool AddArch) const {
514 const llvm::Triple &TT = getTriple();
515 bool IsITANMSVCWindows =
516 TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
517
518 const char *Prefix =
519 IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";
520 const char *Suffix;
521 switch (Type) {
522 case ToolChain::FT_Object:
523 Suffix = IsITANMSVCWindows ? ".obj" : ".o";
524 break;
525 case ToolChain::FT_Static:
526 Suffix = IsITANMSVCWindows ? ".lib" : ".a";
527 break;
528 case ToolChain::FT_Shared:
529 Suffix = TT.isOSWindows()
530 ? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
531 : ".so";
532 break;
533 }
534
535 std::string ArchAndEnv;
536 if (AddArch) {
537 StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
538 const char *Env = TT.isAndroid() ? "-android" : "";
539 ArchAndEnv = ("-" + Arch + Env).str();
540 }
541 return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();
542 }
543
getCompilerRT(const ArgList & Args,StringRef Component,FileType Type) const544 std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
545 FileType Type) const {
546 // Check for runtime files in the new layout without the architecture first.
547 std::string CRTBasename =
548 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
549 for (const auto &LibPath : getLibraryPaths()) {
550 SmallString<128> P(LibPath);
551 llvm::sys::path::append(P, CRTBasename);
552 if (getVFS().exists(P))
553 return std::string(P.str());
554 }
555
556 // Fall back to the old expected compiler-rt name if the new one does not
557 // exist.
558 CRTBasename =
559 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
560 SmallString<128> Path(getCompilerRTPath());
561 llvm::sys::path::append(Path, CRTBasename);
562 return std::string(Path.str());
563 }
564
getCompilerRTArgString(const llvm::opt::ArgList & Args,StringRef Component,FileType Type) const565 const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
566 StringRef Component,
567 FileType Type) const {
568 return Args.MakeArgString(getCompilerRT(Args, Component, Type));
569 }
570
getRuntimePaths() const571 ToolChain::path_list ToolChain::getRuntimePaths() const {
572 path_list Paths;
573 auto addPathForTriple = [this, &Paths](const llvm::Triple &Triple) {
574 SmallString<128> P(D.ResourceDir);
575 llvm::sys::path::append(P, "lib", Triple.str());
576 Paths.push_back(std::string(P.str()));
577 };
578
579 addPathForTriple(getTriple());
580
581 // Android targets may include an API level at the end. We still want to fall
582 // back on a path without the API level.
583 if (getTriple().isAndroid() &&
584 getTriple().getEnvironmentName() != "android") {
585 llvm::Triple TripleWithoutLevel = getTriple();
586 TripleWithoutLevel.setEnvironmentName("android");
587 addPathForTriple(TripleWithoutLevel);
588 }
589
590 return Paths;
591 }
592
getStdlibPaths() const593 ToolChain::path_list ToolChain::getStdlibPaths() const {
594 path_list Paths;
595 SmallString<128> P(D.Dir);
596 llvm::sys::path::append(P, "..", "lib", getTripleString());
597 Paths.push_back(std::string(P.str()));
598
599 return Paths;
600 }
601
getArchSpecificLibPath() const602 std::string ToolChain::getArchSpecificLibPath() const {
603 SmallString<128> Path(getDriver().ResourceDir);
604 llvm::sys::path::append(Path, "lib", getOSLibName(),
605 llvm::Triple::getArchTypeName(getArch()));
606 return std::string(Path.str());
607 }
608
needsProfileRT(const ArgList & Args)609 bool ToolChain::needsProfileRT(const ArgList &Args) {
610 if (Args.hasArg(options::OPT_noprofilelib))
611 return false;
612
613 return Args.hasArg(options::OPT_fprofile_generate) ||
614 Args.hasArg(options::OPT_fprofile_generate_EQ) ||
615 Args.hasArg(options::OPT_fcs_profile_generate) ||
616 Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
617 Args.hasArg(options::OPT_fprofile_instr_generate) ||
618 Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
619 Args.hasArg(options::OPT_fcreate_profile) ||
620 Args.hasArg(options::OPT_forder_file_instrumentation);
621 }
622
needsGCovInstrumentation(const llvm::opt::ArgList & Args)623 bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
624 return Args.hasArg(options::OPT_coverage) ||
625 Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
626 false);
627 }
628
SelectTool(const JobAction & JA) const629 Tool *ToolChain::SelectTool(const JobAction &JA) const {
630 if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
631 if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
632 Action::ActionClass AC = JA.getKind();
633 if (AC == Action::AssembleJobClass && useIntegratedAs())
634 return getClangAs();
635 return getTool(AC);
636 }
637
GetFilePath(const char * Name) const638 std::string ToolChain::GetFilePath(const char *Name) const {
639 return D.GetFilePath(Name, *this);
640 }
641
GetProgramPath(const char * Name) const642 std::string ToolChain::GetProgramPath(const char *Name) const {
643 return D.GetProgramPath(Name, *this);
644 }
645
GetLinkerPath(bool * LinkerIsLLD) const646 std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
647 if (LinkerIsLLD)
648 *LinkerIsLLD = false;
649
650 // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
651 // considered as the linker flavor, e.g. "bfd", "gold", or "lld".
652 const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
653 StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
654
655 // --ld-path= takes precedence over -fuse-ld= and specifies the executable
656 // name. -B, COMPILER_PATH and PATH and consulted if the value does not
657 // contain a path component separator.
658 // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
659 // that --ld-path= points to is lld.
660 if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
661 std::string Path(A->getValue());
662 if (!Path.empty()) {
663 if (llvm::sys::path::parent_path(Path).empty())
664 Path = GetProgramPath(A->getValue());
665 if (llvm::sys::fs::can_execute(Path)) {
666 if (LinkerIsLLD)
667 *LinkerIsLLD = UseLinker == "lld";
668 return std::string(Path);
669 }
670 }
671 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
672 return GetProgramPath(getDefaultLinker());
673 }
674 // If we're passed -fuse-ld= with no argument, or with the argument ld,
675 // then use whatever the default system linker is.
676 if (UseLinker.empty() || UseLinker == "ld") {
677 const char *DefaultLinker = getDefaultLinker();
678 if (llvm::sys::path::is_absolute(DefaultLinker))
679 return std::string(DefaultLinker);
680 else
681 return GetProgramPath(DefaultLinker);
682 }
683
684 // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking
685 // for the linker flavor is brittle. In addition, prepending "ld." or "ld64."
686 // to a relative path is surprising. This is more complex due to priorities
687 // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.
688 if (UseLinker.contains('/'))
689 getDriver().Diag(diag::warn_drv_fuse_ld_path);
690
691 if (llvm::sys::path::is_absolute(UseLinker)) {
692 // If we're passed what looks like an absolute path, don't attempt to
693 // second-guess that.
694 if (llvm::sys::fs::can_execute(UseLinker))
695 return std::string(UseLinker);
696 } else {
697 llvm::SmallString<8> LinkerName;
698 if (Triple.isOSDarwin())
699 LinkerName.append("ld64.");
700 else
701 LinkerName.append("ld.");
702 LinkerName.append(UseLinker);
703
704 std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
705 if (llvm::sys::fs::can_execute(LinkerPath)) {
706 if (LinkerIsLLD)
707 *LinkerIsLLD = UseLinker == "lld";
708 return LinkerPath;
709 }
710 }
711
712 if (A)
713 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
714
715 return GetProgramPath(getDefaultLinker());
716 }
717
GetStaticLibToolPath() const718 std::string ToolChain::GetStaticLibToolPath() const {
719 // TODO: Add support for static lib archiving on Windows
720 if (Triple.isOSDarwin())
721 return GetProgramPath("libtool");
722 return GetProgramPath("llvm-ar");
723 }
724
LookupTypeForExtension(StringRef Ext) const725 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
726 types::ID id = types::lookupTypeForExtension(Ext);
727
728 // Flang always runs the preprocessor and has no notion of "preprocessed
729 // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
730 // them differently.
731 if (D.IsFlangMode() && id == types::TY_PP_Fortran)
732 id = types::TY_Fortran;
733
734 return id;
735 }
736
HasNativeLLVMSupport() const737 bool ToolChain::HasNativeLLVMSupport() const {
738 return false;
739 }
740
isCrossCompiling() const741 bool ToolChain::isCrossCompiling() const {
742 llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
743 switch (HostTriple.getArch()) {
744 // The A32/T32/T16 instruction sets are not separate architectures in this
745 // context.
746 case llvm::Triple::arm:
747 case llvm::Triple::armeb:
748 case llvm::Triple::thumb:
749 case llvm::Triple::thumbeb:
750 return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
751 getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
752 default:
753 return HostTriple.getArch() != getArch();
754 }
755 }
756
getDefaultObjCRuntime(bool isNonFragile) const757 ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
758 return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
759 VersionTuple());
760 }
761
762 llvm::ExceptionHandling
GetExceptionModel(const llvm::opt::ArgList & Args) const763 ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
764 return llvm::ExceptionHandling::None;
765 }
766
isThreadModelSupported(const StringRef Model) const767 bool ToolChain::isThreadModelSupported(const StringRef Model) const {
768 if (Model == "single") {
769 // FIXME: 'single' is only supported on ARM and WebAssembly so far.
770 return Triple.getArch() == llvm::Triple::arm ||
771 Triple.getArch() == llvm::Triple::armeb ||
772 Triple.getArch() == llvm::Triple::thumb ||
773 Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm();
774 } else if (Model == "posix")
775 return true;
776
777 return false;
778 }
779
ComputeLLVMTriple(const ArgList & Args,types::ID InputType) const780 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
781 types::ID InputType) const {
782 switch (getTriple().getArch()) {
783 default:
784 return getTripleString();
785
786 case llvm::Triple::x86_64: {
787 llvm::Triple Triple = getTriple();
788 if (!Triple.isOSBinFormatMachO())
789 return getTripleString();
790
791 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
792 // x86_64h goes in the triple. Other -march options just use the
793 // vanilla triple we already have.
794 StringRef MArch = A->getValue();
795 if (MArch == "x86_64h")
796 Triple.setArchName(MArch);
797 }
798 return Triple.getTriple();
799 }
800 case llvm::Triple::aarch64: {
801 llvm::Triple Triple = getTriple();
802 if (!Triple.isOSBinFormatMachO())
803 return getTripleString();
804
805 if (Triple.isArm64e())
806 return getTripleString();
807
808 // FIXME: older versions of ld64 expect the "arm64" component in the actual
809 // triple string and query it to determine whether an LTO file can be
810 // handled. Remove this when we don't care any more.
811 Triple.setArchName("arm64");
812 return Triple.getTriple();
813 }
814 case llvm::Triple::aarch64_32:
815 return getTripleString();
816 case llvm::Triple::arm:
817 case llvm::Triple::armeb:
818 case llvm::Triple::thumb:
819 case llvm::Triple::thumbeb: {
820 llvm::Triple Triple = getTriple();
821 tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);
822 tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);
823 return Triple.getTriple();
824 }
825 }
826 }
827
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const828 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
829 types::ID InputType) const {
830 return ComputeLLVMTriple(Args, InputType);
831 }
832
computeSysRoot() const833 std::string ToolChain::computeSysRoot() const {
834 return D.SysRoot;
835 }
836
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const837 void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
838 ArgStringList &CC1Args) const {
839 // Each toolchain should provide the appropriate include flags.
840 }
841
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadKind) const842 void ToolChain::addClangTargetOptions(
843 const ArgList &DriverArgs, ArgStringList &CC1Args,
844 Action::OffloadKind DeviceOffloadKind) const {}
845
addClangCC1ASTargetOptions(const ArgList & Args,ArgStringList & CC1ASArgs) const846 void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
847 ArgStringList &CC1ASArgs) const {}
848
addClangWarningOptions(ArgStringList & CC1Args) const849 void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
850
addProfileRTLibs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const851 void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
852 llvm::opt::ArgStringList &CmdArgs) const {
853 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
854 return;
855
856 CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
857 }
858
GetRuntimeLibType(const ArgList & Args) const859 ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
860 const ArgList &Args) const {
861 if (runtimeLibType)
862 return *runtimeLibType;
863
864 const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
865 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
866
867 // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
868 if (LibName == "compiler-rt")
869 runtimeLibType = ToolChain::RLT_CompilerRT;
870 else if (LibName == "libgcc")
871 runtimeLibType = ToolChain::RLT_Libgcc;
872 else if (LibName == "platform")
873 runtimeLibType = GetDefaultRuntimeLibType();
874 else {
875 if (A)
876 getDriver().Diag(diag::err_drv_invalid_rtlib_name)
877 << A->getAsString(Args);
878
879 runtimeLibType = GetDefaultRuntimeLibType();
880 }
881
882 return *runtimeLibType;
883 }
884
GetUnwindLibType(const ArgList & Args) const885 ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
886 const ArgList &Args) const {
887 if (unwindLibType)
888 return *unwindLibType;
889
890 const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
891 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;
892
893 if (LibName == "none")
894 unwindLibType = ToolChain::UNW_None;
895 else if (LibName == "platform" || LibName == "") {
896 ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
897 if (RtLibType == ToolChain::RLT_CompilerRT) {
898 if (getTriple().isAndroid() || getTriple().isOSAIX())
899 unwindLibType = ToolChain::UNW_CompilerRT;
900 else
901 unwindLibType = ToolChain::UNW_None;
902 } else if (RtLibType == ToolChain::RLT_Libgcc)
903 unwindLibType = ToolChain::UNW_Libgcc;
904 } else if (LibName == "libunwind") {
905 if (GetRuntimeLibType(Args) == RLT_Libgcc)
906 getDriver().Diag(diag::err_drv_incompatible_unwindlib);
907 unwindLibType = ToolChain::UNW_CompilerRT;
908 } else if (LibName == "libgcc")
909 unwindLibType = ToolChain::UNW_Libgcc;
910 else {
911 if (A)
912 getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
913 << A->getAsString(Args);
914
915 unwindLibType = GetDefaultUnwindLibType();
916 }
917
918 return *unwindLibType;
919 }
920
GetCXXStdlibType(const ArgList & Args) const921 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
922 if (cxxStdlibType)
923 return *cxxStdlibType;
924
925 const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
926 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
927
928 // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
929 if (LibName == "libc++")
930 cxxStdlibType = ToolChain::CST_Libcxx;
931 else if (LibName == "libstdc++")
932 cxxStdlibType = ToolChain::CST_Libstdcxx;
933 else if (LibName == "platform")
934 cxxStdlibType = GetDefaultCXXStdlibType();
935 else {
936 if (A)
937 getDriver().Diag(diag::err_drv_invalid_stdlib_name)
938 << A->getAsString(Args);
939
940 cxxStdlibType = GetDefaultCXXStdlibType();
941 }
942
943 return *cxxStdlibType;
944 }
945
946 /// Utility function to add a system include directory to CC1 arguments.
addSystemInclude(const ArgList & DriverArgs,ArgStringList & CC1Args,const Twine & Path)947 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
948 ArgStringList &CC1Args,
949 const Twine &Path) {
950 CC1Args.push_back("-internal-isystem");
951 CC1Args.push_back(DriverArgs.MakeArgString(Path));
952 }
953
954 /// Utility function to add a system include directory with extern "C"
955 /// semantics to CC1 arguments.
956 ///
957 /// Note that this should be used rarely, and only for directories that
958 /// historically and for legacy reasons are treated as having implicit extern
959 /// "C" semantics. These semantics are *ignored* by and large today, but its
960 /// important to preserve the preprocessor changes resulting from the
961 /// classification.
addExternCSystemInclude(const ArgList & DriverArgs,ArgStringList & CC1Args,const Twine & Path)962 /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
963 ArgStringList &CC1Args,
964 const Twine &Path) {
965 CC1Args.push_back("-internal-externc-isystem");
966 CC1Args.push_back(DriverArgs.MakeArgString(Path));
967 }
968
addExternCSystemIncludeIfExists(const ArgList & DriverArgs,ArgStringList & CC1Args,const Twine & Path)969 void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
970 ArgStringList &CC1Args,
971 const Twine &Path) {
972 if (llvm::sys::fs::exists(Path))
973 addExternCSystemInclude(DriverArgs, CC1Args, Path);
974 }
975
976 /// Utility function to add a list of system include directories to CC1.
addSystemIncludes(const ArgList & DriverArgs,ArgStringList & CC1Args,ArrayRef<StringRef> Paths)977 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
978 ArgStringList &CC1Args,
979 ArrayRef<StringRef> Paths) {
980 for (const auto &Path : Paths) {
981 CC1Args.push_back("-internal-isystem");
982 CC1Args.push_back(DriverArgs.MakeArgString(Path));
983 }
984 }
985
concat(StringRef Path,const Twine & A,const Twine & B,const Twine & C,const Twine & D)986 /*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
987 const Twine &B, const Twine &C,
988 const Twine &D) {
989 SmallString<128> Result(Path);
990 llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
991 return std::string(Result);
992 }
993
detectLibcxxVersion(StringRef IncludePath) const994 std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
995 std::error_code EC;
996 int MaxVersion = 0;
997 std::string MaxVersionString;
998 SmallString<128> Path(IncludePath);
999 llvm::sys::path::append(Path, "c++");
1000 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
1001 !EC && LI != LE; LI = LI.increment(EC)) {
1002 StringRef VersionText = llvm::sys::path::filename(LI->path());
1003 int Version;
1004 if (VersionText[0] == 'v' &&
1005 !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
1006 if (Version > MaxVersion) {
1007 MaxVersion = Version;
1008 MaxVersionString = std::string(VersionText);
1009 }
1010 }
1011 }
1012 if (!MaxVersion)
1013 return "";
1014 return MaxVersionString;
1015 }
1016
AddClangCXXStdlibIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1017 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1018 ArgStringList &CC1Args) const {
1019 // Header search paths should be handled by each of the subclasses.
1020 // Historically, they have not been, and instead have been handled inside of
1021 // the CC1-layer frontend. As the logic is hoisted out, this generic function
1022 // will slowly stop being called.
1023 //
1024 // While it is being called, replicate a bit of a hack to propagate the
1025 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
1026 // header search paths with it. Once all systems are overriding this
1027 // function, the CC1 flag and this line can be removed.
1028 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
1029 }
1030
AddClangCXXStdlibIsystemArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const1031 void ToolChain::AddClangCXXStdlibIsystemArgs(
1032 const llvm::opt::ArgList &DriverArgs,
1033 llvm::opt::ArgStringList &CC1Args) const {
1034 DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
1035 // This intentionally only looks at -nostdinc++, and not -nostdinc or
1036 // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain
1037 // setups with non-standard search logic for the C++ headers, while still
1038 // allowing users of the toolchain to bring their own C++ headers. Such a
1039 // toolchain likely also has non-standard search logic for the C headers and
1040 // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should
1041 // still work in that case and only be suppressed by an explicit -nostdinc++
1042 // in a project using the toolchain.
1043 if (!DriverArgs.hasArg(options::OPT_nostdincxx))
1044 for (const auto &P :
1045 DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
1046 addSystemInclude(DriverArgs, CC1Args, P);
1047 }
1048
ShouldLinkCXXStdlib(const llvm::opt::ArgList & Args) const1049 bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {
1050 return getDriver().CCCIsCXX() &&
1051 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
1052 options::OPT_nostdlibxx);
1053 }
1054
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const1055 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
1056 ArgStringList &CmdArgs) const {
1057 assert(!Args.hasArg(options::OPT_nostdlibxx) &&
1058 "should not have called this");
1059 CXXStdlibType Type = GetCXXStdlibType(Args);
1060
1061 switch (Type) {
1062 case ToolChain::CST_Libcxx:
1063 CmdArgs.push_back("-lc++");
1064 if (Args.hasArg(options::OPT_fexperimental_library))
1065 CmdArgs.push_back("-lc++experimental");
1066 break;
1067
1068 case ToolChain::CST_Libstdcxx:
1069 CmdArgs.push_back("-lstdc++");
1070 break;
1071 }
1072 }
1073
AddFilePathLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const1074 void ToolChain::AddFilePathLibArgs(const ArgList &Args,
1075 ArgStringList &CmdArgs) const {
1076 for (const auto &LibPath : getFilePaths())
1077 if(LibPath.length() > 0)
1078 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
1079 }
1080
AddCCKextLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const1081 void ToolChain::AddCCKextLibArgs(const ArgList &Args,
1082 ArgStringList &CmdArgs) const {
1083 CmdArgs.push_back("-lcc_kext");
1084 }
1085
isFastMathRuntimeAvailable(const ArgList & Args,std::string & Path) const1086 bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
1087 std::string &Path) const {
1088 // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
1089 // (to keep the linker options consistent with gcc and clang itself).
1090 if (!isOptimizationLevelFast(Args)) {
1091 // Check if -ffast-math or -funsafe-math.
1092 Arg *A =
1093 Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
1094 options::OPT_funsafe_math_optimizations,
1095 options::OPT_fno_unsafe_math_optimizations);
1096
1097 if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
1098 A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
1099 return false;
1100 }
1101 // If crtfastmath.o exists add it to the arguments.
1102 Path = GetFilePath("crtfastmath.o");
1103 return (Path != "crtfastmath.o"); // Not found.
1104 }
1105
addFastMathRuntimeIfAvailable(const ArgList & Args,ArgStringList & CmdArgs) const1106 bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
1107 ArgStringList &CmdArgs) const {
1108 std::string Path;
1109 if (isFastMathRuntimeAvailable(Args, Path)) {
1110 CmdArgs.push_back(Args.MakeArgString(Path));
1111 return true;
1112 }
1113
1114 return false;
1115 }
1116
1117 Expected<SmallVector<std::string>>
getSystemGPUArchs(const llvm::opt::ArgList & Args) const1118 ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
1119 return SmallVector<std::string>();
1120 }
1121
getSupportedSanitizers() const1122 SanitizerMask ToolChain::getSupportedSanitizers() const {
1123 // Return sanitizers which don't require runtime support and are not
1124 // platform dependent.
1125
1126 SanitizerMask Res =
1127 (SanitizerKind::Undefined & ~SanitizerKind::Vptr &
1128 ~SanitizerKind::Function) |
1129 (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
1130 SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
1131 SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
1132 SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
1133 SanitizerKind::Nullability | SanitizerKind::LocalBounds;
1134 if (getTriple().getArch() == llvm::Triple::x86 ||
1135 getTriple().getArch() == llvm::Triple::x86_64 ||
1136 getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||
1137 getTriple().isAArch64() || getTriple().isRISCV())
1138 Res |= SanitizerKind::CFIICall;
1139 if (getTriple().getArch() == llvm::Triple::x86_64 ||
1140 getTriple().isAArch64(64) || getTriple().isRISCV())
1141 Res |= SanitizerKind::ShadowCallStack;
1142 if (getTriple().isAArch64(64))
1143 Res |= SanitizerKind::MemTag;
1144 return Res;
1145 }
1146
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1147 void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
1148 ArgStringList &CC1Args) const {}
1149
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1150 void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
1151 ArgStringList &CC1Args) const {}
1152
1153 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
getDeviceLibs(const ArgList & DriverArgs) const1154 ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
1155 return {};
1156 }
1157
AddIAMCUIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1158 void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
1159 ArgStringList &CC1Args) const {}
1160
separateMSVCFullVersion(unsigned Version)1161 static VersionTuple separateMSVCFullVersion(unsigned Version) {
1162 if (Version < 100)
1163 return VersionTuple(Version);
1164
1165 if (Version < 10000)
1166 return VersionTuple(Version / 100, Version % 100);
1167
1168 unsigned Build = 0, Factor = 1;
1169 for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
1170 Build = Build + (Version % 10) * Factor;
1171 return VersionTuple(Version / 100, Version % 100, Build);
1172 }
1173
1174 VersionTuple
computeMSVCVersion(const Driver * D,const llvm::opt::ArgList & Args) const1175 ToolChain::computeMSVCVersion(const Driver *D,
1176 const llvm::opt::ArgList &Args) const {
1177 const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
1178 const Arg *MSCompatibilityVersion =
1179 Args.getLastArg(options::OPT_fms_compatibility_version);
1180
1181 if (MSCVersion && MSCompatibilityVersion) {
1182 if (D)
1183 D->Diag(diag::err_drv_argument_not_allowed_with)
1184 << MSCVersion->getAsString(Args)
1185 << MSCompatibilityVersion->getAsString(Args);
1186 return VersionTuple();
1187 }
1188
1189 if (MSCompatibilityVersion) {
1190 VersionTuple MSVT;
1191 if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {
1192 if (D)
1193 D->Diag(diag::err_drv_invalid_value)
1194 << MSCompatibilityVersion->getAsString(Args)
1195 << MSCompatibilityVersion->getValue();
1196 } else {
1197 return MSVT;
1198 }
1199 }
1200
1201 if (MSCVersion) {
1202 unsigned Version = 0;
1203 if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {
1204 if (D)
1205 D->Diag(diag::err_drv_invalid_value)
1206 << MSCVersion->getAsString(Args) << MSCVersion->getValue();
1207 } else {
1208 return separateMSVCFullVersion(Version);
1209 }
1210 }
1211
1212 return VersionTuple();
1213 }
1214
TranslateOpenMPTargetArgs(const llvm::opt::DerivedArgList & Args,bool SameTripleAsHost,SmallVectorImpl<llvm::opt::Arg * > & AllocatedArgs) const1215 llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
1216 const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
1217 SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {
1218 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1219 const OptTable &Opts = getDriver().getOpts();
1220 bool Modified = false;
1221
1222 // Handle -Xopenmp-target flags
1223 for (auto *A : Args) {
1224 // Exclude flags which may only apply to the host toolchain.
1225 // Do not exclude flags when the host triple (AuxTriple)
1226 // matches the current toolchain triple. If it is not present
1227 // at all, target and host share a toolchain.
1228 if (A->getOption().matches(options::OPT_m_Group)) {
1229 if (SameTripleAsHost)
1230 DAL->append(A);
1231 else
1232 Modified = true;
1233 continue;
1234 }
1235
1236 unsigned Index;
1237 unsigned Prev;
1238 bool XOpenMPTargetNoTriple =
1239 A->getOption().matches(options::OPT_Xopenmp_target);
1240
1241 if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
1242 llvm::Triple TT(getOpenMPTriple(A->getValue(0)));
1243
1244 // Passing device args: -Xopenmp-target=<triple> -opt=val.
1245 if (TT.getTriple() == getTripleString())
1246 Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
1247 else
1248 continue;
1249 } else if (XOpenMPTargetNoTriple) {
1250 // Passing device args: -Xopenmp-target -opt=val.
1251 Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
1252 } else {
1253 DAL->append(A);
1254 continue;
1255 }
1256
1257 // Parse the argument to -Xopenmp-target.
1258 Prev = Index;
1259 std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
1260 if (!XOpenMPTargetArg || Index > Prev + 1) {
1261 getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
1262 << A->getAsString(Args);
1263 continue;
1264 }
1265 if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
1266 Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
1267 getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
1268 continue;
1269 }
1270 XOpenMPTargetArg->setBaseArg(A);
1271 A = XOpenMPTargetArg.release();
1272 AllocatedArgs.push_back(A);
1273 DAL->append(A);
1274 Modified = true;
1275 }
1276
1277 if (Modified)
1278 return DAL;
1279
1280 delete DAL;
1281 return nullptr;
1282 }
1283
1284 // TODO: Currently argument values separated by space e.g.
1285 // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be
1286 // fixed.
TranslateXarchArgs(const llvm::opt::DerivedArgList & Args,llvm::opt::Arg * & A,llvm::opt::DerivedArgList * DAL,SmallVectorImpl<llvm::opt::Arg * > * AllocatedArgs) const1287 void ToolChain::TranslateXarchArgs(
1288 const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,
1289 llvm::opt::DerivedArgList *DAL,
1290 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1291 const OptTable &Opts = getDriver().getOpts();
1292 unsigned ValuePos = 1;
1293 if (A->getOption().matches(options::OPT_Xarch_device) ||
1294 A->getOption().matches(options::OPT_Xarch_host))
1295 ValuePos = 0;
1296
1297 unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));
1298 unsigned Prev = Index;
1299 std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));
1300
1301 // If the argument parsing failed or more than one argument was
1302 // consumed, the -Xarch_ argument's parameter tried to consume
1303 // extra arguments. Emit an error and ignore.
1304 //
1305 // We also want to disallow any options which would alter the
1306 // driver behavior; that isn't going to work in our model. We
1307 // use options::NoXarchOption to control this.
1308 if (!XarchArg || Index > Prev + 1) {
1309 getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
1310 << A->getAsString(Args);
1311 return;
1312 } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) {
1313 auto &Diags = getDriver().getDiags();
1314 unsigned DiagID =
1315 Diags.getCustomDiagID(DiagnosticsEngine::Error,
1316 "invalid Xarch argument: '%0', not all driver "
1317 "options can be forwared via Xarch argument");
1318 Diags.Report(DiagID) << A->getAsString(Args);
1319 return;
1320 }
1321 XarchArg->setBaseArg(A);
1322 A = XarchArg.release();
1323 if (!AllocatedArgs)
1324 DAL->AddSynthesizedArg(A);
1325 else
1326 AllocatedArgs->push_back(A);
1327 }
1328
TranslateXarchArgs(const llvm::opt::DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind OFK,SmallVectorImpl<llvm::opt::Arg * > * AllocatedArgs) const1329 llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
1330 const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
1331 Action::OffloadKind OFK,
1332 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1333 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1334 bool Modified = false;
1335
1336 bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;
1337 for (Arg *A : Args) {
1338 bool NeedTrans = false;
1339 bool Skip = false;
1340 if (A->getOption().matches(options::OPT_Xarch_device)) {
1341 NeedTrans = IsDevice;
1342 Skip = !IsDevice;
1343 } else if (A->getOption().matches(options::OPT_Xarch_host)) {
1344 NeedTrans = !IsDevice;
1345 Skip = IsDevice;
1346 } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {
1347 // Do not translate -Xarch_ options for non CUDA/HIP toolchain since
1348 // they may need special translation.
1349 // Skip this argument unless the architecture matches BoundArch
1350 if (BoundArch.empty() || A->getValue(0) != BoundArch)
1351 Skip = true;
1352 else
1353 NeedTrans = true;
1354 }
1355 if (NeedTrans || Skip)
1356 Modified = true;
1357 if (NeedTrans)
1358 TranslateXarchArgs(Args, A, DAL, AllocatedArgs);
1359 if (!Skip)
1360 DAL->append(A);
1361 }
1362
1363 if (Modified)
1364 return DAL;
1365
1366 delete DAL;
1367 return nullptr;
1368 }
1369