Home | History | Annotate | Line # | Download | only in ToolChains
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "Hexagon.h"
     10 #include "CommonArgs.h"
     11 #include "InputInfo.h"
     12 #include "clang/Driver/Compilation.h"
     13 #include "clang/Driver/Driver.h"
     14 #include "clang/Driver/DriverDiagnostic.h"
     15 #include "clang/Driver/Options.h"
     16 #include "llvm/ADT/StringExtras.h"
     17 #include "llvm/Option/ArgList.h"
     18 #include "llvm/Support/FileSystem.h"
     19 #include "llvm/Support/Path.h"
     20 #include "llvm/Support/VirtualFileSystem.h"
     21 
     22 using namespace clang::driver;
     23 using namespace clang::driver::tools;
     24 using namespace clang::driver::toolchains;
     25 using namespace clang;
     26 using namespace llvm::opt;
     27 
     28 // Default hvx-length for various versions.
     29 static StringRef getDefaultHvxLength(StringRef Cpu) {
     30   return llvm::StringSwitch<StringRef>(Cpu)
     31       .Case("v60", "64b")
     32       .Case("v62", "64b")
     33       .Case("v65", "64b")
     34       .Default("128b");
     35 }
     36 
     37 static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
     38   // Handle the unsupported values passed to mhvx-length.
     39   if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
     40     StringRef Val = A->getValue();
     41     if (!Val.equals_lower("64b") && !Val.equals_lower("128b"))
     42       D.Diag(diag::err_drv_unsupported_option_argument)
     43           << A->getOption().getName() << Val;
     44   }
     45 }
     46 
     47 // Handle hvx target features explicitly.
     48 static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
     49                                     std::vector<StringRef> &Features,
     50                                     StringRef Cpu, bool &HasHVX) {
     51   // Handle HVX warnings.
     52   handleHVXWarnings(D, Args);
     53 
     54   // Add the +hvx* features based on commandline flags.
     55   StringRef HVXFeature, HVXLength;
     56 
     57   // Handle -mhvx, -mhvx=, -mno-hvx.
     58   if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx,
     59                                options::OPT_mhexagon_hvx,
     60                                options::OPT_mhexagon_hvx_EQ)) {
     61     if (A->getOption().matches(options::OPT_mno_hexagon_hvx))
     62       return;
     63     if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
     64       HasHVX = true;
     65       HVXFeature = Cpu = A->getValue();
     66       HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower());
     67     } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) {
     68       HasHVX = true;
     69       HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu);
     70     }
     71     Features.push_back(HVXFeature);
     72   }
     73 
     74   // Handle -mhvx-length=.
     75   if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
     76     // These flags are valid only if HVX in enabled.
     77     if (!HasHVX)
     78       D.Diag(diag::err_drv_invalid_hvx_length);
     79     else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
     80       HVXLength = A->getValue();
     81   }
     82   // Default hvx-length based on Cpu.
     83   else if (HasHVX)
     84     HVXLength = getDefaultHvxLength(Cpu);
     85 
     86   if (!HVXLength.empty()) {
     87     HVXFeature =
     88         Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower());
     89     Features.push_back(HVXFeature);
     90   }
     91 }
     92 
     93 // Hexagon target features.
     94 void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
     95                                        std::vector<StringRef> &Features) {
     96   handleTargetFeaturesGroup(Args, Features,
     97                             options::OPT_m_hexagon_Features_Group);
     98 
     99   bool UseLongCalls = false;
    100   if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
    101                                options::OPT_mno_long_calls)) {
    102     if (A->getOption().matches(options::OPT_mlong_calls))
    103       UseLongCalls = true;
    104   }
    105 
    106   Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
    107 
    108   bool HasHVX = false;
    109   StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
    110   // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
    111   // have no dependency on micro-architecture.
    112   const bool TinyCore = Cpu.contains('t');
    113 
    114   if (TinyCore)
    115     Cpu = Cpu.take_front(Cpu.size() - 1);
    116 
    117   handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
    118 
    119   if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
    120     D.Diag(diag::warn_drv_vectorize_needs_hvx);
    121 }
    122 
    123 // Hexagon tools start.
    124 void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
    125                                              ArgStringList &CmdArgs) const {
    126 }
    127 
    128 void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
    129                                       const InputInfo &Output,
    130                                       const InputInfoList &Inputs,
    131                                       const ArgList &Args,
    132                                       const char *LinkingOutput) const {
    133   claimNoWarnArgs(Args);
    134 
    135   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
    136   const Driver &D = HTC.getDriver();
    137   ArgStringList CmdArgs;
    138 
    139   CmdArgs.push_back("--arch=hexagon");
    140 
    141   RenderExtraToolArgs(JA, CmdArgs);
    142 
    143   const char *AsName = "llvm-mc";
    144   CmdArgs.push_back("-filetype=obj");
    145   CmdArgs.push_back(Args.MakeArgString(
    146       "-mcpu=hexagon" +
    147       toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
    148 
    149   if (Output.isFilename()) {
    150     CmdArgs.push_back("-o");
    151     CmdArgs.push_back(Output.getFilename());
    152   } else {
    153     assert(Output.isNothing() && "Unexpected output");
    154     CmdArgs.push_back("-fsyntax-only");
    155   }
    156 
    157   if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
    158     CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
    159   }
    160 
    161   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
    162 
    163   // Only pass -x if gcc will understand it; otherwise hope gcc
    164   // understands the suffix correctly. The main use case this would go
    165   // wrong in is for linker inputs if they happened to have an odd
    166   // suffix; really the only way to get this to happen is a command
    167   // like '-x foobar a.c' which will treat a.c like a linker input.
    168   //
    169   // FIXME: For the linker case specifically, can we safely convert
    170   // inputs into '-Wl,' options?
    171   for (const auto &II : Inputs) {
    172     // Don't try to pass LLVM or AST inputs to a generic gcc.
    173     if (types::isLLVMIR(II.getType()))
    174       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
    175           << HTC.getTripleString();
    176     else if (II.getType() == types::TY_AST)
    177       D.Diag(clang::diag::err_drv_no_ast_support)
    178           << HTC.getTripleString();
    179     else if (II.getType() == types::TY_ModuleFile)
    180       D.Diag(diag::err_drv_no_module_support)
    181           << HTC.getTripleString();
    182 
    183     if (II.isFilename())
    184       CmdArgs.push_back(II.getFilename());
    185     else
    186       // Don't render as input, we need gcc to do the translations.
    187       // FIXME: What is this?
    188       II.getInputArg().render(Args, CmdArgs);
    189   }
    190 
    191   auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
    192   C.addCommand(std::make_unique<Command>(JA, *this,
    193                                          ResponseFileSupport::AtFileCurCP(),
    194                                          Exec, CmdArgs, Inputs, Output));
    195 }
    196 
    197 void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
    198                                           ArgStringList &CmdArgs) const {
    199 }
    200 
    201 static void
    202 constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
    203                          const toolchains::HexagonToolChain &HTC,
    204                          const InputInfo &Output, const InputInfoList &Inputs,
    205                          const ArgList &Args, ArgStringList &CmdArgs,
    206                          const char *LinkingOutput) {
    207 
    208   const Driver &D = HTC.getDriver();
    209 
    210   //----------------------------------------------------------------------------
    211   //
    212   //----------------------------------------------------------------------------
    213   bool IsStatic = Args.hasArg(options::OPT_static);
    214   bool IsShared = Args.hasArg(options::OPT_shared);
    215   bool IsPIE = Args.hasArg(options::OPT_pie);
    216   bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
    217   bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
    218   bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
    219   bool UseG0 = false;
    220   const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
    221   bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
    222                  llvm::sys::path::stem(Exec).equals_lower("ld.lld"));
    223   bool UseShared = IsShared && !IsStatic;
    224   StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
    225 
    226   //----------------------------------------------------------------------------
    227   // Silence warnings for various options
    228   //----------------------------------------------------------------------------
    229   Args.ClaimAllArgs(options::OPT_g_Group);
    230   Args.ClaimAllArgs(options::OPT_emit_llvm);
    231   Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
    232                                      // handled somewhere else.
    233   Args.ClaimAllArgs(options::OPT_static_libgcc);
    234 
    235   //----------------------------------------------------------------------------
    236   //
    237   //----------------------------------------------------------------------------
    238   if (Args.hasArg(options::OPT_s))
    239     CmdArgs.push_back("-s");
    240 
    241   if (Args.hasArg(options::OPT_r))
    242     CmdArgs.push_back("-r");
    243 
    244   for (const auto &Opt : HTC.ExtraOpts)
    245     CmdArgs.push_back(Opt.c_str());
    246 
    247   if (!UseLLD) {
    248     CmdArgs.push_back("-march=hexagon");
    249     CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
    250   }
    251 
    252   if (IsShared) {
    253     CmdArgs.push_back("-shared");
    254     // The following should be the default, but doing as hexagon-gcc does.
    255     CmdArgs.push_back("-call_shared");
    256   }
    257 
    258   if (IsStatic)
    259     CmdArgs.push_back("-static");
    260 
    261   if (IsPIE && !IsShared)
    262     CmdArgs.push_back("-pie");
    263 
    264   if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
    265     CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
    266     UseG0 = G.getValue() == 0;
    267   }
    268 
    269   CmdArgs.push_back("-o");
    270   CmdArgs.push_back(Output.getFilename());
    271 
    272   if (HTC.getTriple().isMusl()) {
    273     if (!Args.hasArg(options::OPT_shared, options::OPT_static))
    274       CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
    275 
    276     if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
    277                      options::OPT_nostdlib))
    278       CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
    279     else if (Args.hasArg(options::OPT_shared) &&
    280              !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
    281       CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
    282 
    283     CmdArgs.push_back(
    284         Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
    285     Args.AddAllArgs(CmdArgs,
    286                     {options::OPT_T_Group, options::OPT_e, options::OPT_s,
    287                      options::OPT_t, options::OPT_u_Group});
    288     AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
    289 
    290     if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    291       CmdArgs.push_back("-lclang_rt.builtins-hexagon");
    292       CmdArgs.push_back("-lc");
    293     }
    294     if (D.CCCIsCXX()) {
    295       if (HTC.ShouldLinkCXXStdlib(Args))
    296         HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
    297     }
    298     return;
    299   }
    300 
    301   //----------------------------------------------------------------------------
    302   // moslib
    303   //----------------------------------------------------------------------------
    304   std::vector<std::string> OsLibs;
    305   bool HasStandalone = false;
    306   for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
    307     A->claim();
    308     OsLibs.emplace_back(A->getValue());
    309     HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
    310   }
    311   if (OsLibs.empty()) {
    312     OsLibs.push_back("standalone");
    313     HasStandalone = true;
    314   }
    315 
    316   //----------------------------------------------------------------------------
    317   // Start Files
    318   //----------------------------------------------------------------------------
    319   const std::string MCpuSuffix = "/" + CpuVer.str();
    320   const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
    321   const std::string RootDir =
    322       HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
    323   const std::string StartSubDir =
    324       "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
    325 
    326   auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
    327                       const char *Name) -> std::string {
    328     std::string RelName = SubDir + Name;
    329     std::string P = HTC.GetFilePath(RelName.c_str());
    330     if (llvm::sys::fs::exists(P))
    331       return P;
    332     return RootDir + RelName;
    333   };
    334 
    335   if (IncStdLib && IncStartFiles) {
    336     if (!IsShared) {
    337       if (HasStandalone) {
    338         std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
    339         CmdArgs.push_back(Args.MakeArgString(Crt0SA));
    340       }
    341       std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
    342       CmdArgs.push_back(Args.MakeArgString(Crt0));
    343     }
    344     std::string Init = UseShared
    345           ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
    346           : Find(RootDir, StartSubDir, "/init.o");
    347     CmdArgs.push_back(Args.MakeArgString(Init));
    348   }
    349 
    350   //----------------------------------------------------------------------------
    351   // Library Search Paths
    352   //----------------------------------------------------------------------------
    353   const ToolChain::path_list &LibPaths = HTC.getFilePaths();
    354   for (const auto &LibPath : LibPaths)
    355     CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
    356 
    357   //----------------------------------------------------------------------------
    358   //
    359   //----------------------------------------------------------------------------
    360   Args.AddAllArgs(CmdArgs,
    361                   {options::OPT_T_Group, options::OPT_e, options::OPT_s,
    362                    options::OPT_t, options::OPT_u_Group});
    363 
    364   AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
    365 
    366   //----------------------------------------------------------------------------
    367   // Libraries
    368   //----------------------------------------------------------------------------
    369   if (IncStdLib && IncDefLibs) {
    370     if (D.CCCIsCXX()) {
    371       if (HTC.ShouldLinkCXXStdlib(Args))
    372         HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
    373       CmdArgs.push_back("-lm");
    374     }
    375 
    376     CmdArgs.push_back("--start-group");
    377 
    378     if (!IsShared) {
    379       for (StringRef Lib : OsLibs)
    380         CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
    381       CmdArgs.push_back("-lc");
    382     }
    383     CmdArgs.push_back("-lgcc");
    384 
    385     CmdArgs.push_back("--end-group");
    386   }
    387 
    388   //----------------------------------------------------------------------------
    389   // End files
    390   //----------------------------------------------------------------------------
    391   if (IncStdLib && IncStartFiles) {
    392     std::string Fini = UseShared
    393           ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
    394           : Find(RootDir, StartSubDir, "/fini.o");
    395     CmdArgs.push_back(Args.MakeArgString(Fini));
    396   }
    397 }
    398 
    399 void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
    400                                    const InputInfo &Output,
    401                                    const InputInfoList &Inputs,
    402                                    const ArgList &Args,
    403                                    const char *LinkingOutput) const {
    404   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
    405 
    406   ArgStringList CmdArgs;
    407   constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
    408                            LinkingOutput);
    409 
    410   const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
    411   C.addCommand(std::make_unique<Command>(JA, *this,
    412                                          ResponseFileSupport::AtFileCurCP(),
    413                                          Exec, CmdArgs, Inputs, Output));
    414 }
    415 // Hexagon tools end.
    416 
    417 /// Hexagon Toolchain
    418 
    419 std::string HexagonToolChain::getHexagonTargetDir(
    420       const std::string &InstalledDir,
    421       const SmallVectorImpl<std::string> &PrefixDirs) const {
    422   std::string InstallRelDir;
    423   const Driver &D = getDriver();
    424 
    425   // Locate the rest of the toolchain ...
    426   for (auto &I : PrefixDirs)
    427     if (D.getVFS().exists(I))
    428       return I;
    429 
    430   if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
    431     return InstallRelDir;
    432 
    433   return InstalledDir;
    434 }
    435 
    436 Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
    437       const ArgList &Args) {
    438   StringRef Gn = "";
    439   if (Arg *A = Args.getLastArg(options::OPT_G)) {
    440     Gn = A->getValue();
    441   } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
    442                              options::OPT_fPIC)) {
    443     Gn = "0";
    444   }
    445 
    446   unsigned G;
    447   if (!Gn.getAsInteger(10, G))
    448     return G;
    449 
    450   return None;
    451 }
    452 
    453 void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
    454       ToolChain::path_list &LibPaths) const {
    455   const Driver &D = getDriver();
    456 
    457   //----------------------------------------------------------------------------
    458   // -L Args
    459   //----------------------------------------------------------------------------
    460   for (Arg *A : Args.filtered(options::OPT_L))
    461     for (const char *Value : A->getValues())
    462       LibPaths.push_back(Value);
    463 
    464   //----------------------------------------------------------------------------
    465   // Other standard paths
    466   //----------------------------------------------------------------------------
    467   std::vector<std::string> RootDirs;
    468   std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
    469             std::back_inserter(RootDirs));
    470 
    471   std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
    472                                               D.PrefixDirs);
    473   if (llvm::find(RootDirs, TargetDir) == RootDirs.end())
    474     RootDirs.push_back(TargetDir);
    475 
    476   bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
    477   // Assume G0 with -shared.
    478   bool HasG0 = Args.hasArg(options::OPT_shared);
    479   if (auto G = getSmallDataThreshold(Args))
    480     HasG0 = G.getValue() == 0;
    481 
    482   const std::string CpuVer = GetTargetCPUVersion(Args).str();
    483   for (auto &Dir : RootDirs) {
    484     std::string LibDir = Dir + "/hexagon/lib";
    485     std::string LibDirCpu = LibDir + '/' + CpuVer;
    486     if (HasG0) {
    487       if (HasPIC)
    488         LibPaths.push_back(LibDirCpu + "/G0/pic");
    489       LibPaths.push_back(LibDirCpu + "/G0");
    490     }
    491     LibPaths.push_back(LibDirCpu);
    492     LibPaths.push_back(LibDir);
    493   }
    494 }
    495 
    496 HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
    497                                    const llvm::opt::ArgList &Args)
    498     : Linux(D, Triple, Args) {
    499   const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
    500                                                     D.PrefixDirs);
    501 
    502   // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
    503   // program paths
    504   const std::string BinDir(TargetDir + "/bin");
    505   if (D.getVFS().exists(BinDir))
    506     getProgramPaths().push_back(BinDir);
    507 
    508   ToolChain::path_list &LibPaths = getFilePaths();
    509 
    510   // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
    511   // 'elf' OS type, so the Linux paths are not appropriate. When we actually
    512   // support 'linux' we'll need to fix this up
    513   LibPaths.clear();
    514   getHexagonLibraryPaths(Args, LibPaths);
    515 }
    516 
    517 HexagonToolChain::~HexagonToolChain() {}
    518 
    519 void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
    520                                            ArgStringList &CmdArgs) const {
    521   CXXStdlibType Type = GetCXXStdlibType(Args);
    522   switch (Type) {
    523   case ToolChain::CST_Libcxx:
    524     CmdArgs.push_back("-lc++");
    525     CmdArgs.push_back("-lc++abi");
    526     CmdArgs.push_back("-lunwind");
    527     break;
    528 
    529   case ToolChain::CST_Libstdcxx:
    530     CmdArgs.push_back("-lstdc++");
    531     break;
    532   }
    533 }
    534 
    535 Tool *HexagonToolChain::buildAssembler() const {
    536   return new tools::hexagon::Assembler(*this);
    537 }
    538 
    539 Tool *HexagonToolChain::buildLinker() const {
    540   return new tools::hexagon::Linker(*this);
    541 }
    542 
    543 unsigned HexagonToolChain::getOptimizationLevel(
    544     const llvm::opt::ArgList &DriverArgs) const {
    545   // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
    546   Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
    547   if (!A)
    548     return 0;
    549 
    550   if (A->getOption().matches(options::OPT_O0))
    551     return 0;
    552   if (A->getOption().matches(options::OPT_Ofast) ||
    553       A->getOption().matches(options::OPT_O4))
    554     return 3;
    555   assert(A->getNumValues() != 0);
    556   StringRef S(A->getValue());
    557   if (S == "s" || S == "z" || S.empty())
    558     return 2;
    559   if (S == "g")
    560     return 1;
    561 
    562   unsigned OptLevel;
    563   if (S.getAsInteger(10, OptLevel))
    564     return 0;
    565   return OptLevel;
    566 }
    567 
    568 void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
    569                                              ArgStringList &CC1Args,
    570                                              Action::OffloadKind) const {
    571 
    572   bool UseInitArrayDefault = getTriple().isMusl();
    573 
    574   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
    575                           options::OPT_fno_use_init_array,
    576                           UseInitArrayDefault))
    577     CC1Args.push_back("-fno-use-init-array");
    578 
    579   if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
    580     CC1Args.push_back("-target-feature");
    581     CC1Args.push_back("+reserved-r19");
    582   }
    583   if (isAutoHVXEnabled(DriverArgs)) {
    584     CC1Args.push_back("-mllvm");
    585     CC1Args.push_back("-hexagon-autohvx");
    586   }
    587 }
    588 
    589 void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    590                                                  ArgStringList &CC1Args) const {
    591   if (DriverArgs.hasArg(options::OPT_nostdinc) ||
    592       DriverArgs.hasArg(options::OPT_nostdlibinc))
    593     return;
    594 
    595   const Driver &D = getDriver();
    596   if (!D.SysRoot.empty()) {
    597     SmallString<128> P(D.SysRoot);
    598     if (getTriple().isMusl())
    599       llvm::sys::path::append(P, "usr/include");
    600     else
    601       llvm::sys::path::append(P, "include");
    602     addExternCSystemInclude(DriverArgs, CC1Args, P.str());
    603     return;
    604   }
    605 
    606   std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
    607                                               D.PrefixDirs);
    608   addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
    609 }
    610 
    611 void HexagonToolChain::addLibCxxIncludePaths(
    612     const llvm::opt::ArgList &DriverArgs,
    613     llvm::opt::ArgStringList &CC1Args) const {
    614   const Driver &D = getDriver();
    615   if (!D.SysRoot.empty() && getTriple().isMusl())
    616     addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",
    617                              DriverArgs, CC1Args);
    618   else if (getTriple().isMusl())
    619     addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
    620                              CC1Args);
    621   else {
    622     std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
    623     addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
    624                              DriverArgs, CC1Args);
    625   }
    626 }
    627 void HexagonToolChain::addLibStdCxxIncludePaths(
    628     const llvm::opt::ArgList &DriverArgs,
    629     llvm::opt::ArgStringList &CC1Args) const {
    630   const Driver &D = getDriver();
    631   std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
    632   addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
    633                            DriverArgs, CC1Args);
    634 }
    635 
    636 ToolChain::CXXStdlibType
    637 HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
    638   Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
    639   if (!A) {
    640     if (getTriple().isMusl())
    641       return ToolChain::CST_Libcxx;
    642     else
    643       return ToolChain::CST_Libstdcxx;
    644   }
    645   StringRef Value = A->getValue();
    646   if (Value != "libstdc++" && Value != "libc++")
    647     getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
    648 
    649   if (Value == "libstdc++")
    650     return ToolChain::CST_Libstdcxx;
    651   else if (Value == "libc++")
    652     return ToolChain::CST_Libcxx;
    653   else
    654     return ToolChain::CST_Libstdcxx;
    655 }
    656 
    657 bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
    658   if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
    659                                options::OPT_fno_vectorize))
    660     return A->getOption().matches(options::OPT_fvectorize);
    661   return false;
    662 }
    663 
    664 //
    665 // Returns the default CPU for Hexagon. This is the default compilation target
    666 // if no Hexagon processor is selected at the command-line.
    667 //
    668 const StringRef HexagonToolChain::GetDefaultCPU() {
    669   return "hexagonv60";
    670 }
    671 
    672 const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
    673   Arg *CpuArg = nullptr;
    674   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
    675     CpuArg = A;
    676 
    677   StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
    678   if (CPU.startswith("hexagon"))
    679     return CPU.substr(sizeof("hexagon") - 1);
    680   return CPU;
    681 }
    682