brintos

brintos / llvm-project-archived public Read only

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