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
49using namespace clang;
50using namespace driver;
51using namespace tools;
52using namespace llvm;
53using namespace llvm::opt;
54
55static 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
60static 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
76ToolChain::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
92llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
93ToolChain::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
119void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
120  Triple.setEnvironment(Env);
121  if (EffectiveTriple != llvm::Triple())
122    EffectiveTriple.setEnvironment(Env);
123}
124
125ToolChain::~ToolChain() = default;
126
127llvm::vfs::FileSystem &ToolChain::getVFS() const {
128  return getDriver().getVFS();
129}
130
131bool ToolChain::useIntegratedAs() const {
132  return Args.hasFlag(options::OPT_fintegrated_as,
133                      options::OPT_fno_integrated_as,
134                      IsIntegratedAssemblerDefault());
135}
136
137bool 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
165bool ToolChain::useRelaxRelocations() const {
166  return ENABLE_X86_RELAX_RELOCATIONS;
167}
168
169bool ToolChain::defaultToIEEELongDouble() const {
170  return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
171}
172
173SanitizerArgs
174ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
175  SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
176  SanitizerArgsChecked = true;
177  return SanArgs;
178}
179
180const XRayArgs& ToolChain::getXRayArgs() const {
181  if (!XRayArguments)
182    XRayArguments.reset(new XRayArgs(*this, Args));
183  return *XRayArguments;
184}
185
186namespace {
187
188struct DriverSuffix {
189  const char *Suffix;
190  const char *ModeFlag;
191};
192
193} // namespace
194
195static 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.
228static 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
238static 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
271ParsedClangName
272ToolChain::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
296StringRef 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
321std::string ToolChain::getInputFilename(const InputInfo &Input) const {
322  return Input.getFilename();
323}
324
325ToolChain::UnwindTableLevel
326ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
327  return UnwindTableLevel::None;
328}
329
330Tool *ToolChain::getClang() const {
331  if (!Clang)
332    Clang.reset(new tools::Clang(*this, useIntegratedBackend()));
333  return Clang.get();
334}
335
336Tool *ToolChain::getFlang() const {
337  if (!Flang)
338    Flang.reset(new tools::Flang(*this));
339  return Flang.get();
340}
341
342Tool *ToolChain::buildAssembler() const {
343  return new tools::ClangAs(*this);
344}
345
346Tool *ToolChain::buildLinker() const {
347  llvm_unreachable("Linking is not supported by this toolchain");
348}
349
350Tool *ToolChain::buildStaticLibTool() const {
351  llvm_unreachable("Creating static lib is not supported by this toolchain");
352}
353
354Tool *ToolChain::getAssemble() const {
355  if (!Assemble)
356    Assemble.reset(buildAssembler());
357  return Assemble.get();
358}
359
360Tool *ToolChain::getClangAs() const {
361  if (!Assemble)
362    Assemble.reset(new tools::ClangAs(*this));
363  return Assemble.get();
364}
365
366Tool *ToolChain::getLink() const {
367  if (!Link)
368    Link.reset(buildLinker());
369  return Link.get();
370}
371
372Tool *ToolChain::getStaticLibTool() const {
373  if (!StaticLibTool)
374    StaticLibTool.reset(buildStaticLibTool());
375  return StaticLibTool.get();
376}
377
378Tool *ToolChain::getIfsMerge() const {
379  if (!IfsMerge)
380    IfsMerge.reset(new tools::ifstool::Merger(*this));
381  return IfsMerge.get();
382}
383
384Tool *ToolChain::getOffloadBundler() const {
385  if (!OffloadBundler)
386    OffloadBundler.reset(new tools::OffloadBundler(*this));
387  return OffloadBundler.get();
388}
389
390Tool *ToolChain::getOffloadPackager() const {
391  if (!OffloadPackager)
392    OffloadPackager.reset(new tools::OffloadPackager(*this));
393  return OffloadPackager.get();
394}
395
396Tool *ToolChain::getLinkerWrapper() const {
397  if (!LinkerWrapper)
398    LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
399  return LinkerWrapper.get();
400}
401
402Tool *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
447static 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
470StringRef 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
490std::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
503std::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
510std::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
544std::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
565const 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
571ToolChain::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
593ToolChain::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
602std::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
609bool 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
623bool 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
629Tool *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
638std::string ToolChain::GetFilePath(const char *Name) const {
639  return D.GetFilePath(Name, *this);
640}
641
642std::string ToolChain::GetProgramPath(const char *Name) const {
643  return D.GetProgramPath(Name, *this);
644}
645
646std::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
718std::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
725types::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
737bool ToolChain::HasNativeLLVMSupport() const {
738  return false;
739}
740
741bool 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
757ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
758  return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
759                     VersionTuple());
760}
761
762llvm::ExceptionHandling
763ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
764  return llvm::ExceptionHandling::None;
765}
766
767bool 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
780std::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
828std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
829                                                   types::ID InputType) const {
830  return ComputeLLVMTriple(Args, InputType);
831}
832
833std::string ToolChain::computeSysRoot() const {
834  return D.SysRoot;
835}
836
837void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
838                                          ArgStringList &CC1Args) const {
839  // Each toolchain should provide the appropriate include flags.
840}
841
842void ToolChain::addClangTargetOptions(
843    const ArgList &DriverArgs, ArgStringList &CC1Args,
844    Action::OffloadKind DeviceOffloadKind) const {}
845
846void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
847                                           ArgStringList &CC1ASArgs) const {}
848
849void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
850
851void 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
859ToolChain::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
885ToolChain::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
921ToolChain::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.
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.
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
969void 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.
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
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
994std::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
1017void 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
1031void 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
1049bool 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
1055void 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
1074void 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
1081void ToolChain::AddCCKextLibArgs(const ArgList &Args,
1082                                 ArgStringList &CmdArgs) const {
1083  CmdArgs.push_back("-lcc_kext");
1084}
1085
1086bool 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
1106bool 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
1117Expected<SmallVector<std::string>>
1118ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
1119  return SmallVector<std::string>();
1120}
1121
1122SanitizerMask 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
1147void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
1148                                   ArgStringList &CC1Args) const {}
1149
1150void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
1151                                  ArgStringList &CC1Args) const {}
1152
1153llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
1154ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
1155  return {};
1156}
1157
1158void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
1159                                    ArgStringList &CC1Args) const {}
1160
1161static 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
1174VersionTuple
1175ToolChain::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
1215llvm::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.
1287void 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
1329llvm::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