brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.6 KiB · 084f517 Raw
815 lines · cpp
1//===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//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 "Hexagon.h"10#include "clang/Driver/CommonArgs.h"11#include "clang/Driver/Compilation.h"12#include "clang/Driver/Driver.h"13#include "clang/Driver/InputInfo.h"14#include "clang/Options/Options.h"15#include "llvm/Option/ArgList.h"16#include "llvm/Support/FileSystem.h"17#include "llvm/Support/Path.h"18#include "llvm/Support/VirtualFileSystem.h"19 20using namespace clang::driver;21using namespace clang::driver::tools;22using namespace clang::driver::toolchains;23using namespace clang;24using namespace llvm::opt;25 26// Default hvx-length for various versions.27static StringRef getDefaultHvxLength(StringRef HvxVer) {28  return llvm::StringSwitch<StringRef>(HvxVer)29      .Case("v60", "64b")30      .Case("v62", "64b")31      .Case("v65", "64b")32      .Default("128b");33}34 35static void handleHVXWarnings(const Driver &D, const ArgList &Args) {36  // Handle the unsupported values passed to mhvx-length.37  if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {38    StringRef Val = A->getValue();39    if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))40      D.Diag(diag::err_drv_unsupported_option_argument)41          << A->getSpelling() << Val;42  }43}44 45// Handle hvx target features explicitly.46static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,47                                    std::vector<StringRef> &Features,48                                    StringRef Cpu, bool &HasHVX) {49  // Handle HVX warnings.50  handleHVXWarnings(D, Args);51 52  auto makeFeature = [&Args](Twine T, bool Enable) -> StringRef {53    const std::string &S = T.str();54    StringRef Opt(S);55    Opt.consume_back("=");56    if (Opt.starts_with("mno-"))57      Opt = Opt.drop_front(4);58    else if (Opt.starts_with("m"))59      Opt = Opt.drop_front(1);60    return Args.MakeArgString(Twine(Enable ? "+" : "-") + Twine(Opt));61  };62 63  auto withMinus = [](StringRef S) -> std::string {64    return "-" + S.str();65  };66 67  // Drop tiny core suffix for HVX version.68  std::string HvxVer =69      (Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();70  HasHVX = false;71 72  // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags73  // are both present, the last one wins.74  Arg *HvxEnablingArg =75      Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,76                      options::OPT_mno_hexagon_hvx);77  if (HvxEnablingArg) {78    if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))79      HvxEnablingArg = nullptr;80  }81 82  if (HvxEnablingArg) {83    // If -mhvx[=] was given, it takes precedence.84    if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,85                                 options::OPT_mhexagon_hvx_EQ)) {86      // If the version was given, set HvxVer. Otherwise HvxVer87      // will remain equal to the CPU version.88      if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))89        HvxVer = StringRef(A->getValue()).lower();90    }91    HasHVX = true;92    Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));93  } else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {94    // If there was an explicit -mno-hvx, add -hvx to target features.95    Features.push_back(makeFeature(A->getOption().getName(), false));96  }97 98  StringRef HvxLen = getDefaultHvxLength(HvxVer);99 100  // Handle -mhvx-length=.101  if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {102    // These flags are valid only if HVX in enabled.103    if (!HasHVX)104      D.Diag(diag::err_drv_needs_hvx) << withMinus(A->getOption().getName());105    else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))106      HvxLen = A->getValue();107  }108 109  if (HasHVX) {110    StringRef L = makeFeature(Twine("hvx-length") + HvxLen.lower(), true);111    Features.push_back(L);112  }113 114  unsigned HvxVerNum;115  // getAsInteger returns 'true' on error.116  if (StringRef(HvxVer).drop_front(1).getAsInteger(10, HvxVerNum))117    HvxVerNum = 0;118 119  // Handle HVX floating point flags.120  auto checkFlagHvxVersion =121      [&](auto FlagOn, auto FlagOff,122          unsigned MinVerNum) -> std::optional<StringRef> {123    // Return an std::optional<StringRef>:124    // - std::nullopt indicates a verification failure, or that the flag was not125    //   present in Args.126    // - Otherwise the returned value is that name of the feature to add127    //   to Features.128    Arg *A = Args.getLastArg(FlagOn, FlagOff);129    if (!A)130      return std::nullopt;131 132    StringRef OptName = A->getOption().getName();133    if (A->getOption().matches(FlagOff))134      return makeFeature(OptName, false);135 136    if (!HasHVX) {137      D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);138      return std::nullopt;139    }140    if (HvxVerNum < MinVerNum) {141      D.Diag(diag::err_drv_needs_hvx_version)142          << withMinus(OptName) << ("v" + std::to_string(HvxVerNum));143      return std::nullopt;144    }145    return makeFeature(OptName, true);146  };147 148  if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,149                                   options::OPT_mno_hexagon_hvx_qfloat, 68)) {150    Features.push_back(*F);151  }152  if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,153                                   options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {154    Features.push_back(*F);155  }156}157 158// Hexagon target features.159void hexagon::getHexagonTargetFeatures(const Driver &D,160                                       const llvm::Triple &Triple,161                                       const ArgList &Args,162                                       std::vector<StringRef> &Features) {163  handleTargetFeaturesGroup(D, Triple, Args, Features,164                            options::OPT_m_hexagon_Features_Group);165 166  bool UseLongCalls = false;167  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,168                               options::OPT_mno_long_calls)) {169    if (A->getOption().matches(options::OPT_mlong_calls))170      UseLongCalls = true;171  }172 173  Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");174 175  bool HasHVX = false;176  StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));177  // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors178  // have no dependency on micro-architecture.179  const bool TinyCore = Cpu.contains('t');180 181  if (TinyCore)182    Cpu = Cpu.take_front(Cpu.size() - 1);183 184  handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);185 186  if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)187    D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";188}189 190// Hexagon tools start.191void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,192                                             ArgStringList &CmdArgs) const {193}194 195void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,196                                      const InputInfo &Output,197                                      const InputInfoList &Inputs,198                                      const ArgList &Args,199                                      const char *LinkingOutput) const {200  claimNoWarnArgs(Args);201 202  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());203  const Driver &D = HTC.getDriver();204  ArgStringList CmdArgs;205 206  CmdArgs.push_back("--arch=hexagon");207 208  RenderExtraToolArgs(JA, CmdArgs);209 210  const char *AsName = "llvm-mc";211  CmdArgs.push_back("-filetype=obj");212  CmdArgs.push_back(Args.MakeArgString(213      "-mcpu=hexagon" +214      toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));215 216  addSanitizerRuntimes(HTC, Args, CmdArgs);217 218  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");219  if (Output.isFilename()) {220    CmdArgs.push_back("-o");221    CmdArgs.push_back(Output.getFilename());222  } else {223    CmdArgs.push_back("-fsyntax-only");224  }225 226  if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,227                               options::OPT_mno_hexagon_hvx_ieee_fp)) {228    if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))229      CmdArgs.push_back("-mhvx-ieee-fp");230  }231 232  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {233    CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(*G)));234  }235 236  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);237 238  // Only pass -x if gcc will understand it; otherwise hope gcc239  // understands the suffix correctly. The main use case this would go240  // wrong in is for linker inputs if they happened to have an odd241  // suffix; really the only way to get this to happen is a command242  // like '-x foobar a.c' which will treat a.c like a linker input.243  //244  // FIXME: For the linker case specifically, can we safely convert245  // inputs into '-Wl,' options?246  for (const auto &II : Inputs) {247    // Don't try to pass LLVM or AST inputs to a generic gcc.248    if (types::isLLVMIR(II.getType()))249      D.Diag(clang::diag::err_drv_no_linker_llvm_support)250          << HTC.getTripleString();251    else if (II.getType() == types::TY_AST)252      D.Diag(clang::diag::err_drv_no_ast_support)253          << HTC.getTripleString();254    else if (II.getType() == types::TY_ModuleFile)255      D.Diag(diag::err_drv_no_module_support)256          << HTC.getTripleString();257 258    if (II.isFilename())259      CmdArgs.push_back(II.getFilename());260    else261      // Don't render as input, we need gcc to do the translations.262      // FIXME: What is this?263      II.getInputArg().render(Args, CmdArgs);264  }265 266  auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));267  C.addCommand(std::make_unique<Command>(JA, *this,268                                         ResponseFileSupport::AtFileCurCP(),269                                         Exec, CmdArgs, Inputs, Output));270}271 272void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,273                                          ArgStringList &CmdArgs) const {274}275 276static void277constructHexagonLinkArgs(Compilation &C, const JobAction &JA,278                         const toolchains::HexagonToolChain &HTC,279                         const InputInfo &Output, const InputInfoList &Inputs,280                         const ArgList &Args, ArgStringList &CmdArgs,281                         const char *LinkingOutput) {282 283  const Driver &D = HTC.getDriver();284 285  //----------------------------------------------------------------------------286  //287  //----------------------------------------------------------------------------288  bool IsStatic = Args.hasArg(options::OPT_static);289  bool IsShared = Args.hasArg(options::OPT_shared);290  bool IsPIE = Args.hasArg(options::OPT_pie);291  bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);292  bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);293  bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);294  bool UseG0 = false;295  bool UseLLD = false;296  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath(&UseLLD));297  UseLLD = UseLLD || llvm::sys::path::filename(Exec).ends_with("ld.lld") ||298           llvm::sys::path::stem(Exec).ends_with("ld.lld");299  bool UseShared = IsShared && !IsStatic;300  StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);301 302  bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);303  bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);304 305  //----------------------------------------------------------------------------306  // Silence warnings for various options307  //----------------------------------------------------------------------------308  Args.ClaimAllArgs(options::OPT_g_Group);309  Args.ClaimAllArgs(options::OPT_emit_llvm);310  Args.ClaimAllArgs(options::OPT_w); // Other warning options are already311                                     // handled somewhere else.312  Args.ClaimAllArgs(options::OPT_static_libgcc);313 314  CmdArgs.push_back("--eh-frame-hdr");315  //----------------------------------------------------------------------------316  //317  //----------------------------------------------------------------------------318  if (Args.hasArg(options::OPT_s))319    CmdArgs.push_back("-s");320 321  if (Args.hasArg(options::OPT_r))322    CmdArgs.push_back("-r");323 324  for (const auto &Opt : HTC.ExtraOpts)325    CmdArgs.push_back(Opt.c_str());326 327  if (!UseLLD) {328    CmdArgs.push_back("-march=hexagon");329    CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));330  }331 332  if (IsShared) {333    CmdArgs.push_back("-shared");334    // The following should be the default, but doing as hexagon-gcc does.335    CmdArgs.push_back("-call_shared");336  }337 338  if (IsStatic)339    CmdArgs.push_back("-static");340 341  if (IsPIE && !IsShared)342    CmdArgs.push_back("-pie");343 344  if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {345    CmdArgs.push_back(Args.MakeArgString("-G" + Twine(*G)));346    UseG0 = *G == 0;347  }348 349  CmdArgs.push_back("-o");350  CmdArgs.push_back(Output.getFilename());351 352  if (HTC.getTriple().isMusl()) {353    if (!Args.hasArg(options::OPT_shared, options::OPT_static))354      CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");355 356    if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,357                     options::OPT_nostdlib))358      CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));359    else if (Args.hasArg(options::OPT_shared) &&360             !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))361      CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));362 363    CmdArgs.push_back(364        Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));365    Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,366                              options::OPT_t, options::OPT_u_Group});367    AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);368 369    ToolChain::UnwindLibType UNW = HTC.GetUnwindLibType(Args);370 371    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {372      if (NeedsSanitizerDeps) {373        linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);374 375        if (UNW != ToolChain::UNW_None)376          CmdArgs.push_back("-lunwind");377      }378      if (NeedsXRayDeps)379        linkXRayRuntimeDeps(HTC, Args, CmdArgs);380 381      if (!Args.hasArg(options::OPT_nolibc))382        CmdArgs.push_back("-lc");383      CmdArgs.push_back("-lclang_rt.builtins-hexagon");384    }385    if (D.CCCIsCXX()) {386      if (HTC.ShouldLinkCXXStdlib(Args))387        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);388    }389    const ToolChain::path_list &LibPaths = HTC.getFilePaths();390    for (const auto &LibPath : LibPaths)391      CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));392    Args.ClaimAllArgs(options::OPT_L);393    return;394  }395 396  //----------------------------------------------------------------------------397  // moslib398  //----------------------------------------------------------------------------399  std::vector<std::string> OsLibs;400  bool HasStandalone = false;401  for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {402    A->claim();403    OsLibs.emplace_back(A->getValue());404    HasStandalone = HasStandalone || (OsLibs.back() == "standalone");405  }406  if (OsLibs.empty()) {407    OsLibs.push_back("standalone");408    HasStandalone = true;409  }410 411  //----------------------------------------------------------------------------412  // Start Files413  //----------------------------------------------------------------------------414  const std::string MCpuSuffix = "/" + CpuVer.str();415  const std::string MCpuG0Suffix = MCpuSuffix + "/G0";416  const std::string RootDir =417      HTC.getHexagonTargetDir(D.Dir, D.PrefixDirs) + "/";418  const std::string StartSubDir =419      "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);420 421  auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,422                      const char *Name) -> std::string {423    std::string RelName = SubDir + Name;424    std::string P = HTC.GetFilePath(RelName.c_str());425    if (llvm::sys::fs::exists(P))426      return P;427    return RootDir + RelName;428  };429 430  if (IncStdLib && IncStartFiles) {431    if (!IsShared) {432      if (HasStandalone) {433        std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");434        CmdArgs.push_back(Args.MakeArgString(Crt0SA));435      }436      std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");437      CmdArgs.push_back(Args.MakeArgString(Crt0));438    }439    std::string Init = UseShared440          ? Find(RootDir, StartSubDir + "/pic", "/initS.o")441          : Find(RootDir, StartSubDir, "/init.o");442    CmdArgs.push_back(Args.MakeArgString(Init));443  }444 445  //----------------------------------------------------------------------------446  // Library Search Paths447  //----------------------------------------------------------------------------448  const ToolChain::path_list &LibPaths = HTC.getFilePaths();449  for (const auto &LibPath : LibPaths)450    CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));451  Args.ClaimAllArgs(options::OPT_L);452 453  //----------------------------------------------------------------------------454  //455  //----------------------------------------------------------------------------456  Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,457                            options::OPT_t, options::OPT_u_Group});458 459  AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);460 461  //----------------------------------------------------------------------------462  // Libraries463  //----------------------------------------------------------------------------464  if (IncStdLib && IncDefLibs) {465    if (D.CCCIsCXX()) {466      if (HTC.ShouldLinkCXXStdlib(Args))467        HTC.AddCXXStdlibLibArgs(Args, CmdArgs);468      CmdArgs.push_back("-lm");469    }470 471    CmdArgs.push_back("--start-group");472 473    if (!IsShared) {474      for (StringRef Lib : OsLibs)475        CmdArgs.push_back(Args.MakeArgString("-l" + Lib));476      if (!Args.hasArg(options::OPT_nolibc))477        CmdArgs.push_back("-lc");478    }479    CmdArgs.push_back("-lgcc");480 481    CmdArgs.push_back("--end-group");482  }483 484  //----------------------------------------------------------------------------485  // End files486  //----------------------------------------------------------------------------487  if (IncStdLib && IncStartFiles) {488    std::string Fini = UseShared489          ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")490          : Find(RootDir, StartSubDir, "/fini.o");491    CmdArgs.push_back(Args.MakeArgString(Fini));492  }493}494 495void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,496                                   const InputInfo &Output,497                                   const InputInfoList &Inputs,498                                   const ArgList &Args,499                                   const char *LinkingOutput) const {500  auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());501 502  ArgStringList CmdArgs;503  constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,504                           LinkingOutput);505 506  const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());507  C.addCommand(std::make_unique<Command>(JA, *this,508                                         ResponseFileSupport::AtFileCurCP(),509                                         Exec, CmdArgs, Inputs, Output));510}511// Hexagon tools end.512 513/// Hexagon Toolchain514 515std::string HexagonToolChain::getHexagonTargetDir(516      const std::string &InstalledDir,517      const SmallVectorImpl<std::string> &PrefixDirs) const {518  std::string InstallRelDir;519  const Driver &D = getDriver();520 521  // Locate the rest of the toolchain ...522  for (auto &I : PrefixDirs)523    if (D.getVFS().exists(I))524      return I;525 526  if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))527    return InstallRelDir;528 529  return InstalledDir;530}531 532std::optional<unsigned>533HexagonToolChain::getSmallDataThreshold(const ArgList &Args) {534  StringRef Gn = "";535  if (Arg *A = Args.getLastArg(options::OPT_G)) {536    Gn = A->getValue();537  } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,538                             options::OPT_fPIC)) {539    Gn = "0";540  }541 542  unsigned G;543  if (!Gn.getAsInteger(10, G))544    return G;545 546  return std::nullopt;547}548 549std::string HexagonToolChain::getCompilerRTPath() const {550  SmallString<128> Dir(getDriver().SysRoot);551  llvm::sys::path::append(Dir, "usr", "lib");552  if (!SelectedMultilibs.empty()) {553    Dir += SelectedMultilibs.back().gccSuffix();554  }555  return std::string(Dir);556}557 558void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,559      ToolChain::path_list &LibPaths) const {560  const Driver &D = getDriver();561 562  //----------------------------------------------------------------------------563  // -L Args564  //----------------------------------------------------------------------------565  for (Arg *A : Args.filtered(options::OPT_L))566    llvm::append_range(LibPaths, A->getValues());567 568  //----------------------------------------------------------------------------569  // Other standard paths570  //----------------------------------------------------------------------------571  std::vector<std::string> RootDirs;572  std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),573            std::back_inserter(RootDirs));574 575  std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);576  if (!llvm::is_contained(RootDirs, TargetDir))577    RootDirs.push_back(TargetDir);578 579  bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);580  // Assume G0 with -shared.581  bool HasG0 = Args.hasArg(options::OPT_shared);582  if (auto G = getSmallDataThreshold(Args))583    HasG0 = *G == 0;584 585  const std::string CpuVer = GetTargetCPUVersion(Args).str();586  for (auto &Dir : RootDirs) {587    std::string LibDir = Dir + "/hexagon/lib";588    std::string LibDirCpu = LibDir + '/' + CpuVer;589    if (HasG0) {590      if (HasPIC)591        LibPaths.push_back(LibDirCpu + "/G0/pic");592      LibPaths.push_back(LibDirCpu + "/G0");593    }594    LibPaths.push_back(LibDirCpu);595    LibPaths.push_back(LibDir);596  }597}598 599HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,600                                   const llvm::opt::ArgList &Args)601    : Linux(D, Triple, Args) {602  const std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);603 604  // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to605  // program paths606  const std::string BinDir(TargetDir + "/bin");607  if (D.getVFS().exists(BinDir))608    getProgramPaths().push_back(BinDir);609 610  ToolChain::path_list &LibPaths = getFilePaths();611 612  // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets613  // 'elf' OS type, so the Linux paths are not appropriate. When we actually614  // support 'linux' we'll need to fix this up615  LibPaths.clear();616  getHexagonLibraryPaths(Args, LibPaths);617}618 619HexagonToolChain::~HexagonToolChain() {}620 621void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,622                                           ArgStringList &CmdArgs) const {623  CXXStdlibType Type = GetCXXStdlibType(Args);624  ToolChain::UnwindLibType UNW = GetUnwindLibType(Args);625  if (UNW != ToolChain::UNW_None && UNW != ToolChain::UNW_CompilerRT) {626    const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);627    if (A) {628      getDriver().Diag(diag::err_drv_unsupported_unwind_for_platform)629          << A->getValue() << getTriple().normalize();630      return;631    }632  }633 634  switch (Type) {635  case ToolChain::CST_Libcxx:636    CmdArgs.push_back("-lc++");637    if (Args.hasArg(options::OPT_fexperimental_library))638      CmdArgs.push_back("-lc++experimental");639    CmdArgs.push_back("-lc++abi");640    if (UNW != ToolChain::UNW_None)641      CmdArgs.push_back("-lunwind");642    break;643 644  case ToolChain::CST_Libstdcxx:645    CmdArgs.push_back("-lstdc++");646    break;647  }648}649 650Tool *HexagonToolChain::buildAssembler() const {651  return new tools::hexagon::Assembler(*this);652}653 654Tool *HexagonToolChain::buildLinker() const {655  return new tools::hexagon::Linker(*this);656}657 658unsigned HexagonToolChain::getOptimizationLevel(659    const llvm::opt::ArgList &DriverArgs) const {660  // Copied in large part from lib/Frontend/CompilerInvocation.cpp.661  Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);662  if (!A)663    return 0;664 665  if (A->getOption().matches(options::OPT_O0))666    return 0;667  if (A->getOption().matches(options::OPT_Ofast) ||668      A->getOption().matches(options::OPT_O4))669    return 3;670  assert(A->getNumValues() != 0);671  StringRef S(A->getValue());672  if (S == "s" || S == "z" || S.empty())673    return 2;674  if (S == "g")675    return 1;676 677  unsigned OptLevel;678  if (S.getAsInteger(10, OptLevel))679    return 0;680  return OptLevel;681}682 683void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,684                                             ArgStringList &CC1Args,685                                             Action::OffloadKind) const {686 687  bool UseInitArrayDefault = getTriple().isMusl();688 689  if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,690                          options::OPT_fno_use_init_array,691                          UseInitArrayDefault))692    CC1Args.push_back("-fno-use-init-array");693 694  if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {695    CC1Args.push_back("-target-feature");696    CC1Args.push_back("+reserved-r19");697  }698  if (isAutoHVXEnabled(DriverArgs)) {699    CC1Args.push_back("-mllvm");700    CC1Args.push_back("-hexagon-autohvx");701  }702}703 704void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,705                                                 ArgStringList &CC1Args) const {706  if (DriverArgs.hasArg(options::OPT_nostdinc))707    return;708 709  const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();710  const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();711 712  const Driver &D = getDriver();713  SmallString<128> ResourceDirInclude(D.ResourceDir);714  if (!IsELF) {715    llvm::sys::path::append(ResourceDirInclude, "include");716    if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&717        (!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))718      addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);719  }720  if (DriverArgs.hasArg(options::OPT_nostdlibinc))721    return;722 723  const bool HasSysRoot = !D.SysRoot.empty();724  if (HasSysRoot) {725    SmallString<128> P(D.SysRoot);726    if (IsLinuxMusl)727      llvm::sys::path::append(P, "usr/include");728    else729      llvm::sys::path::append(P, "include");730 731    addExternCSystemInclude(DriverArgs, CC1Args, P.str());732    // LOCAL_INCLUDE_DIR733    addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");734    // TOOL_INCLUDE_DIR735    AddMultilibIncludeArgs(DriverArgs, CC1Args);736  }737 738  if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)739    addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);740 741  if (HasSysRoot)742    return;743  std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);744  addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");745}746 747void HexagonToolChain::addLibCxxIncludePaths(748    const llvm::opt::ArgList &DriverArgs,749    llvm::opt::ArgStringList &CC1Args) const {750  const Driver &D = getDriver();751  if (!D.SysRoot.empty() && getTriple().isMusl())752    addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",753                             DriverArgs, CC1Args);754  else if (getTriple().isMusl())755    addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,756                             CC1Args);757  else {758    std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);759    addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",760                             DriverArgs, CC1Args);761  }762}763void HexagonToolChain::addLibStdCxxIncludePaths(764    const llvm::opt::ArgList &DriverArgs,765    llvm::opt::ArgStringList &CC1Args) const {766  const Driver &D = getDriver();767  std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);768  addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",769                           DriverArgs, CC1Args);770}771 772ToolChain::CXXStdlibType773HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {774  Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);775  if (!A) {776    if (getTriple().isMusl())777      return ToolChain::CST_Libcxx;778    else779      return ToolChain::CST_Libstdcxx;780  }781  StringRef Value = A->getValue();782  if (Value != "libstdc++" && Value != "libc++")783    getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);784 785  if (Value == "libstdc++")786    return ToolChain::CST_Libstdcxx;787  else if (Value == "libc++")788    return ToolChain::CST_Libcxx;789  else790    return ToolChain::CST_Libstdcxx;791}792 793bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {794  if (Arg *A = Args.getLastArg(options::OPT_fvectorize,795                               options::OPT_fno_vectorize))796    return A->getOption().matches(options::OPT_fvectorize);797  return false;798}799 800//801// Returns the default CPU for Hexagon. This is the default compilation target802// if no Hexagon processor is selected at the command-line.803//804StringRef HexagonToolChain::GetDefaultCPU() { return "hexagonv68"; }805 806StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {807  Arg *CpuArg = nullptr;808  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))809    CpuArg = A;810 811  StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();812  CPU.consume_front("hexagon");813  return CPU;814}815