xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp (revision 6c05f3a74f30934ee60919cc97e16ec69b542b06)
10b57cec5SDimitry Andric //===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "Hexagon.h"
100b57cec5SDimitry Andric #include "CommonArgs.h"
110b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
120b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
130b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
14fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h"
150b57cec5SDimitry Andric #include "clang/Driver/Options.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
170b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
180b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
190b57cec5SDimitry Andric #include "llvm/Support/Path.h"
200b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace clang::driver;
230b57cec5SDimitry Andric using namespace clang::driver::tools;
240b57cec5SDimitry Andric using namespace clang::driver::toolchains;
250b57cec5SDimitry Andric using namespace clang;
260b57cec5SDimitry Andric using namespace llvm::opt;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric // Default hvx-length for various versions.
290eae32dcSDimitry Andric static StringRef getDefaultHvxLength(StringRef HvxVer) {
300eae32dcSDimitry Andric   return llvm::StringSwitch<StringRef>(HvxVer)
310b57cec5SDimitry Andric       .Case("v60", "64b")
320b57cec5SDimitry Andric       .Case("v62", "64b")
330b57cec5SDimitry Andric       .Case("v65", "64b")
340b57cec5SDimitry Andric       .Default("128b");
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
380b57cec5SDimitry Andric   // Handle the unsupported values passed to mhvx-length.
390b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
400b57cec5SDimitry Andric     StringRef Val = A->getValue();
41fe6060f1SDimitry Andric     if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))
420b57cec5SDimitry Andric       D.Diag(diag::err_drv_unsupported_option_argument)
43bdd1243dSDimitry Andric           << A->getSpelling() << Val;
440b57cec5SDimitry Andric   }
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric // Handle hvx target features explicitly.
480b57cec5SDimitry Andric static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
490b57cec5SDimitry Andric                                     std::vector<StringRef> &Features,
505ffd83dbSDimitry Andric                                     StringRef Cpu, bool &HasHVX) {
510b57cec5SDimitry Andric   // Handle HVX warnings.
520b57cec5SDimitry Andric   handleHVXWarnings(D, Args);
530b57cec5SDimitry Andric 
540eae32dcSDimitry Andric   auto makeFeature = [&Args](Twine T, bool Enable) -> StringRef {
550eae32dcSDimitry Andric     const std::string &S = T.str();
560eae32dcSDimitry Andric     StringRef Opt(S);
570fca6ea1SDimitry Andric     Opt.consume_back("=");
585f757f3fSDimitry Andric     if (Opt.starts_with("mno-"))
590eae32dcSDimitry Andric       Opt = Opt.drop_front(4);
605f757f3fSDimitry Andric     else if (Opt.starts_with("m"))
610eae32dcSDimitry Andric       Opt = Opt.drop_front(1);
620eae32dcSDimitry Andric     return Args.MakeArgString(Twine(Enable ? "+" : "-") + Twine(Opt));
630eae32dcSDimitry Andric   };
640b57cec5SDimitry Andric 
650eae32dcSDimitry Andric   auto withMinus = [](StringRef S) -> std::string {
660eae32dcSDimitry Andric     return "-" + S.str();
670eae32dcSDimitry Andric   };
680eae32dcSDimitry Andric 
690eae32dcSDimitry Andric   // Drop tiny core suffix for HVX version.
700eae32dcSDimitry Andric   std::string HvxVer =
710eae32dcSDimitry Andric       (Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();
720eae32dcSDimitry Andric   HasHVX = false;
730eae32dcSDimitry Andric 
74d56accc7SDimitry Andric   // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags
75d56accc7SDimitry Andric   // are both present, the last one wins.
76d56accc7SDimitry Andric   Arg *HvxEnablingArg =
77d56accc7SDimitry Andric       Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,
78d56accc7SDimitry Andric                       options::OPT_mno_hexagon_hvx);
79d56accc7SDimitry Andric   if (HvxEnablingArg) {
80d56accc7SDimitry Andric     if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))
81d56accc7SDimitry Andric       HvxEnablingArg = nullptr;
820b57cec5SDimitry Andric   }
830eae32dcSDimitry Andric 
84d56accc7SDimitry Andric   if (HvxEnablingArg) {
85d56accc7SDimitry Andric     // If -mhvx[=] was given, it takes precedence.
86d56accc7SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,
87d56accc7SDimitry Andric                                  options::OPT_mhexagon_hvx_EQ)) {
88d56accc7SDimitry Andric       // If the version was given, set HvxVer. Otherwise HvxVer
89d56accc7SDimitry Andric       // will remain equal to the CPU version.
900eae32dcSDimitry Andric       if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))
91d56accc7SDimitry Andric         HvxVer = StringRef(A->getValue()).lower();
92d56accc7SDimitry Andric     }
930eae32dcSDimitry Andric     HasHVX = true;
940eae32dcSDimitry Andric     Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));
950eae32dcSDimitry Andric   } else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {
960eae32dcSDimitry Andric     // If there was an explicit -mno-hvx, add -hvx to target features.
970eae32dcSDimitry Andric     Features.push_back(makeFeature(A->getOption().getName(), false));
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric 
1000eae32dcSDimitry Andric   StringRef HvxLen = getDefaultHvxLength(HvxVer);
1010eae32dcSDimitry Andric 
1020b57cec5SDimitry Andric   // Handle -mhvx-length=.
1030b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
1040b57cec5SDimitry Andric     // These flags are valid only if HVX in enabled.
1050b57cec5SDimitry Andric     if (!HasHVX)
1060eae32dcSDimitry Andric       D.Diag(diag::err_drv_needs_hvx) << withMinus(A->getOption().getName());
1070b57cec5SDimitry Andric     else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
1080eae32dcSDimitry Andric       HvxLen = A->getValue();
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric 
1110eae32dcSDimitry Andric   if (HasHVX) {
1120eae32dcSDimitry Andric     StringRef L = makeFeature(Twine("hvx-length") + HvxLen.lower(), true);
1130eae32dcSDimitry Andric     Features.push_back(L);
1140eae32dcSDimitry Andric   }
1150eae32dcSDimitry Andric 
1160eae32dcSDimitry Andric   unsigned HvxVerNum;
1170eae32dcSDimitry Andric   // getAsInteger returns 'true' on error.
1180eae32dcSDimitry Andric   if (StringRef(HvxVer).drop_front(1).getAsInteger(10, HvxVerNum))
1190eae32dcSDimitry Andric     HvxVerNum = 0;
1200eae32dcSDimitry Andric 
1210eae32dcSDimitry Andric   // Handle HVX floating point flags.
122bdd1243dSDimitry Andric   auto checkFlagHvxVersion =
123bdd1243dSDimitry Andric       [&](auto FlagOn, auto FlagOff,
124bdd1243dSDimitry Andric           unsigned MinVerNum) -> std::optional<StringRef> {
125bdd1243dSDimitry Andric     // Return an std::optional<StringRef>:
126bdd1243dSDimitry Andric     // - std::nullopt indicates a verification failure, or that the flag was not
1270eae32dcSDimitry Andric     //   present in Args.
1280eae32dcSDimitry Andric     // - Otherwise the returned value is that name of the feature to add
1290eae32dcSDimitry Andric     //   to Features.
1300eae32dcSDimitry Andric     Arg *A = Args.getLastArg(FlagOn, FlagOff);
1310eae32dcSDimitry Andric     if (!A)
132bdd1243dSDimitry Andric       return std::nullopt;
1330eae32dcSDimitry Andric 
1340eae32dcSDimitry Andric     StringRef OptName = A->getOption().getName();
1350eae32dcSDimitry Andric     if (A->getOption().matches(FlagOff))
1360eae32dcSDimitry Andric       return makeFeature(OptName, false);
1370eae32dcSDimitry Andric 
1380eae32dcSDimitry Andric     if (!HasHVX) {
1390eae32dcSDimitry Andric       D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);
140bdd1243dSDimitry Andric       return std::nullopt;
1410eae32dcSDimitry Andric     }
1420eae32dcSDimitry Andric     if (HvxVerNum < MinVerNum) {
1430eae32dcSDimitry Andric       D.Diag(diag::err_drv_needs_hvx_version)
1440eae32dcSDimitry Andric           << withMinus(OptName) << ("v" + std::to_string(HvxVerNum));
145bdd1243dSDimitry Andric       return std::nullopt;
1460eae32dcSDimitry Andric     }
1470eae32dcSDimitry Andric     return makeFeature(OptName, true);
1480eae32dcSDimitry Andric   };
1490eae32dcSDimitry Andric 
1500eae32dcSDimitry Andric   if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,
1510eae32dcSDimitry Andric                                    options::OPT_mno_hexagon_hvx_qfloat, 68)) {
1520eae32dcSDimitry Andric     Features.push_back(*F);
1530eae32dcSDimitry Andric   }
1540eae32dcSDimitry Andric   if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,
1550eae32dcSDimitry Andric                                    options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {
1560eae32dcSDimitry Andric     Features.push_back(*F);
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric // Hexagon target features.
16106c3fb27SDimitry Andric void hexagon::getHexagonTargetFeatures(const Driver &D,
16206c3fb27SDimitry Andric                                        const llvm::Triple &Triple,
16306c3fb27SDimitry Andric                                        const ArgList &Args,
1640b57cec5SDimitry Andric                                        std::vector<StringRef> &Features) {
16506c3fb27SDimitry Andric   handleTargetFeaturesGroup(D, Triple, Args, Features,
1660b57cec5SDimitry Andric                             options::OPT_m_hexagon_Features_Group);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   bool UseLongCalls = false;
1690b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
1700b57cec5SDimitry Andric                                options::OPT_mno_long_calls)) {
1710b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_mlong_calls))
1720b57cec5SDimitry Andric       UseLongCalls = true;
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   bool HasHVX = false;
1785ffd83dbSDimitry Andric   StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
1795ffd83dbSDimitry Andric   // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
1805ffd83dbSDimitry Andric   // have no dependency on micro-architecture.
1815ffd83dbSDimitry Andric   const bool TinyCore = Cpu.contains('t');
1825ffd83dbSDimitry Andric 
1835ffd83dbSDimitry Andric   if (TinyCore)
1845ffd83dbSDimitry Andric     Cpu = Cpu.take_front(Cpu.size() - 1);
1855ffd83dbSDimitry Andric 
1865ffd83dbSDimitry Andric   handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
1890eae32dcSDimitry Andric     D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric // Hexagon tools start.
1930b57cec5SDimitry Andric void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
1940b57cec5SDimitry Andric                                              ArgStringList &CmdArgs) const {
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
1980b57cec5SDimitry Andric                                       const InputInfo &Output,
1990b57cec5SDimitry Andric                                       const InputInfoList &Inputs,
2000b57cec5SDimitry Andric                                       const ArgList &Args,
2010b57cec5SDimitry Andric                                       const char *LinkingOutput) const {
2020b57cec5SDimitry Andric   claimNoWarnArgs(Args);
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
2050b57cec5SDimitry Andric   const Driver &D = HTC.getDriver();
2060b57cec5SDimitry Andric   ArgStringList CmdArgs;
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   CmdArgs.push_back("--arch=hexagon");
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   RenderExtraToolArgs(JA, CmdArgs);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   const char *AsName = "llvm-mc";
2130b57cec5SDimitry Andric   CmdArgs.push_back("-filetype=obj");
2140b57cec5SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(
2150b57cec5SDimitry Andric       "-mcpu=hexagon" +
2160b57cec5SDimitry Andric       toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
2170b57cec5SDimitry Andric 
218349cc55cSDimitry Andric   addSanitizerRuntimes(HTC, Args, CmdArgs);
219349cc55cSDimitry Andric 
2205f757f3fSDimitry Andric   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
2210b57cec5SDimitry Andric   if (Output.isFilename()) {
2220b57cec5SDimitry Andric     CmdArgs.push_back("-o");
2230b57cec5SDimitry Andric     CmdArgs.push_back(Output.getFilename());
2240b57cec5SDimitry Andric   } else {
2250b57cec5SDimitry Andric     CmdArgs.push_back("-fsyntax-only");
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric 
2280eae32dcSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,
2290eae32dcSDimitry Andric                                options::OPT_mno_hexagon_hvx_ieee_fp)) {
2300eae32dcSDimitry Andric     if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))
2310eae32dcSDimitry Andric       CmdArgs.push_back("-mhvx-ieee-fp");
2320eae32dcSDimitry Andric   }
2330eae32dcSDimitry Andric 
2340b57cec5SDimitry Andric   if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
23581ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(*G)));
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   // Only pass -x if gcc will understand it; otherwise hope gcc
2410b57cec5SDimitry Andric   // understands the suffix correctly. The main use case this would go
2420b57cec5SDimitry Andric   // wrong in is for linker inputs if they happened to have an odd
2430b57cec5SDimitry Andric   // suffix; really the only way to get this to happen is a command
2440b57cec5SDimitry Andric   // like '-x foobar a.c' which will treat a.c like a linker input.
2450b57cec5SDimitry Andric   //
2460b57cec5SDimitry Andric   // FIXME: For the linker case specifically, can we safely convert
2470b57cec5SDimitry Andric   // inputs into '-Wl,' options?
2480b57cec5SDimitry Andric   for (const auto &II : Inputs) {
2490b57cec5SDimitry Andric     // Don't try to pass LLVM or AST inputs to a generic gcc.
2500b57cec5SDimitry Andric     if (types::isLLVMIR(II.getType()))
2510b57cec5SDimitry Andric       D.Diag(clang::diag::err_drv_no_linker_llvm_support)
2520b57cec5SDimitry Andric           << HTC.getTripleString();
2530b57cec5SDimitry Andric     else if (II.getType() == types::TY_AST)
2540b57cec5SDimitry Andric       D.Diag(clang::diag::err_drv_no_ast_support)
2550b57cec5SDimitry Andric           << HTC.getTripleString();
2560b57cec5SDimitry Andric     else if (II.getType() == types::TY_ModuleFile)
2570b57cec5SDimitry Andric       D.Diag(diag::err_drv_no_module_support)
2580b57cec5SDimitry Andric           << HTC.getTripleString();
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric     if (II.isFilename())
2610b57cec5SDimitry Andric       CmdArgs.push_back(II.getFilename());
2620b57cec5SDimitry Andric     else
2630b57cec5SDimitry Andric       // Don't render as input, we need gcc to do the translations.
2640b57cec5SDimitry Andric       // FIXME: What is this?
2650b57cec5SDimitry Andric       II.getInputArg().render(Args, CmdArgs);
2660b57cec5SDimitry Andric   }
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
269e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
270e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
271e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
2750b57cec5SDimitry Andric                                           ArgStringList &CmdArgs) const {
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric static void
2790b57cec5SDimitry Andric constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
2800b57cec5SDimitry Andric                          const toolchains::HexagonToolChain &HTC,
2810b57cec5SDimitry Andric                          const InputInfo &Output, const InputInfoList &Inputs,
2820b57cec5SDimitry Andric                          const ArgList &Args, ArgStringList &CmdArgs,
2830b57cec5SDimitry Andric                          const char *LinkingOutput) {
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   const Driver &D = HTC.getDriver();
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   //----------------------------------------------------------------------------
2880b57cec5SDimitry Andric   //
2890b57cec5SDimitry Andric   //----------------------------------------------------------------------------
2900b57cec5SDimitry Andric   bool IsStatic = Args.hasArg(options::OPT_static);
2910b57cec5SDimitry Andric   bool IsShared = Args.hasArg(options::OPT_shared);
2920b57cec5SDimitry Andric   bool IsPIE = Args.hasArg(options::OPT_pie);
2930b57cec5SDimitry Andric   bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
2940b57cec5SDimitry Andric   bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
2950b57cec5SDimitry Andric   bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
2960b57cec5SDimitry Andric   bool UseG0 = false;
29771ac745dSDimitry Andric   bool UseLLD = false;
29871ac745dSDimitry Andric   const char *Exec = Args.MakeArgString(HTC.GetLinkerPath(&UseLLD));
29971ac745dSDimitry Andric   UseLLD = UseLLD || llvm::sys::path::filename(Exec).ends_with("ld.lld") ||
30071ac745dSDimitry Andric            llvm::sys::path::stem(Exec).ends_with("ld.lld");
3010b57cec5SDimitry Andric   bool UseShared = IsShared && !IsStatic;
302480093f4SDimitry Andric   StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
3030b57cec5SDimitry Andric 
304349cc55cSDimitry Andric   bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
3050eae32dcSDimitry Andric   bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
306349cc55cSDimitry Andric 
3070b57cec5SDimitry Andric   //----------------------------------------------------------------------------
3080b57cec5SDimitry Andric   // Silence warnings for various options
3090b57cec5SDimitry Andric   //----------------------------------------------------------------------------
3100b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_g_Group);
3110b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_emit_llvm);
3120b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
3130b57cec5SDimitry Andric                                      // handled somewhere else.
3140b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_static_libgcc);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   //----------------------------------------------------------------------------
3170b57cec5SDimitry Andric   //
3180b57cec5SDimitry Andric   //----------------------------------------------------------------------------
3190b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_s))
3200b57cec5SDimitry Andric     CmdArgs.push_back("-s");
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   if (Args.hasArg(options::OPT_r))
3230b57cec5SDimitry Andric     CmdArgs.push_back("-r");
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   for (const auto &Opt : HTC.ExtraOpts)
3260b57cec5SDimitry Andric     CmdArgs.push_back(Opt.c_str());
3270b57cec5SDimitry Andric 
328480093f4SDimitry Andric   if (!UseLLD) {
3290b57cec5SDimitry Andric     CmdArgs.push_back("-march=hexagon");
3300b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
331480093f4SDimitry Andric   }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   if (IsShared) {
3340b57cec5SDimitry Andric     CmdArgs.push_back("-shared");
3350b57cec5SDimitry Andric     // The following should be the default, but doing as hexagon-gcc does.
3360b57cec5SDimitry Andric     CmdArgs.push_back("-call_shared");
3370b57cec5SDimitry Andric   }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   if (IsStatic)
3400b57cec5SDimitry Andric     CmdArgs.push_back("-static");
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   if (IsPIE && !IsShared)
3430b57cec5SDimitry Andric     CmdArgs.push_back("-pie");
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
346bdd1243dSDimitry Andric     CmdArgs.push_back(Args.MakeArgString("-G" + Twine(*G)));
347bdd1243dSDimitry Andric     UseG0 = *G == 0;
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   CmdArgs.push_back("-o");
3510b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
3520b57cec5SDimitry Andric 
3535ffd83dbSDimitry Andric   if (HTC.getTriple().isMusl()) {
3545ffd83dbSDimitry Andric     if (!Args.hasArg(options::OPT_shared, options::OPT_static))
3555ffd83dbSDimitry Andric       CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
3565ffd83dbSDimitry Andric 
3575ffd83dbSDimitry Andric     if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
3585ffd83dbSDimitry Andric                      options::OPT_nostdlib))
3595ffd83dbSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
3605ffd83dbSDimitry Andric     else if (Args.hasArg(options::OPT_shared) &&
3615ffd83dbSDimitry Andric              !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
3625ffd83dbSDimitry Andric       CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
3635ffd83dbSDimitry Andric 
3645ffd83dbSDimitry Andric     CmdArgs.push_back(
3655ffd83dbSDimitry Andric         Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
3665f757f3fSDimitry Andric     Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
3675ffd83dbSDimitry Andric                               options::OPT_t, options::OPT_u_Group});
3685ffd83dbSDimitry Andric     AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
3695ffd83dbSDimitry Andric 
3700fca6ea1SDimitry Andric     ToolChain::UnwindLibType UNW = HTC.GetUnwindLibType(Args);
3710fca6ea1SDimitry Andric 
3725ffd83dbSDimitry Andric     if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
373349cc55cSDimitry Andric       if (NeedsSanitizerDeps) {
3745f757f3fSDimitry Andric         linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);
375349cc55cSDimitry Andric 
3760fca6ea1SDimitry Andric         if (UNW != ToolChain::UNW_None)
377349cc55cSDimitry Andric           CmdArgs.push_back("-lunwind");
378349cc55cSDimitry Andric       }
3790eae32dcSDimitry Andric       if (NeedsXRayDeps)
3805f757f3fSDimitry Andric         linkXRayRuntimeDeps(HTC, Args, CmdArgs);
381349cc55cSDimitry Andric 
3825f757f3fSDimitry Andric       if (!Args.hasArg(options::OPT_nolibc))
3835ffd83dbSDimitry Andric         CmdArgs.push_back("-lc");
384*6c05f3a7SDimitry Andric       CmdArgs.push_back("-lclang_rt.builtins-hexagon");
3855ffd83dbSDimitry Andric     }
3865ffd83dbSDimitry Andric     if (D.CCCIsCXX()) {
3875ffd83dbSDimitry Andric       if (HTC.ShouldLinkCXXStdlib(Args))
3885ffd83dbSDimitry Andric         HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
3895ffd83dbSDimitry Andric     }
3908a4dda33SDimitry Andric     const ToolChain::path_list &LibPaths = HTC.getFilePaths();
3918a4dda33SDimitry Andric     for (const auto &LibPath : LibPaths)
3928a4dda33SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
3938a4dda33SDimitry Andric     Args.ClaimAllArgs(options::OPT_L);
3945ffd83dbSDimitry Andric     return;
3955ffd83dbSDimitry Andric   }
3965ffd83dbSDimitry Andric 
3970b57cec5SDimitry Andric   //----------------------------------------------------------------------------
3980b57cec5SDimitry Andric   // moslib
3990b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4000b57cec5SDimitry Andric   std::vector<std::string> OsLibs;
4010b57cec5SDimitry Andric   bool HasStandalone = false;
4020b57cec5SDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
4030b57cec5SDimitry Andric     A->claim();
4040b57cec5SDimitry Andric     OsLibs.emplace_back(A->getValue());
4050b57cec5SDimitry Andric     HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric   if (OsLibs.empty()) {
4080b57cec5SDimitry Andric     OsLibs.push_back("standalone");
4090b57cec5SDimitry Andric     HasStandalone = true;
4100b57cec5SDimitry Andric   }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4130b57cec5SDimitry Andric   // Start Files
4140b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4150b57cec5SDimitry Andric   const std::string MCpuSuffix = "/" + CpuVer.str();
4160b57cec5SDimitry Andric   const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
4170b57cec5SDimitry Andric   const std::string RootDir =
4180fca6ea1SDimitry Andric       HTC.getHexagonTargetDir(D.Dir, D.PrefixDirs) + "/";
4190b57cec5SDimitry Andric   const std::string StartSubDir =
4200b57cec5SDimitry Andric       "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
4230b57cec5SDimitry Andric                       const char *Name) -> std::string {
4240b57cec5SDimitry Andric     std::string RelName = SubDir + Name;
4250b57cec5SDimitry Andric     std::string P = HTC.GetFilePath(RelName.c_str());
4260b57cec5SDimitry Andric     if (llvm::sys::fs::exists(P))
4270b57cec5SDimitry Andric       return P;
4280b57cec5SDimitry Andric     return RootDir + RelName;
4290b57cec5SDimitry Andric   };
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   if (IncStdLib && IncStartFiles) {
4320b57cec5SDimitry Andric     if (!IsShared) {
4330b57cec5SDimitry Andric       if (HasStandalone) {
4340b57cec5SDimitry Andric         std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
4350b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString(Crt0SA));
4360b57cec5SDimitry Andric       }
4370b57cec5SDimitry Andric       std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
4380b57cec5SDimitry Andric       CmdArgs.push_back(Args.MakeArgString(Crt0));
4390b57cec5SDimitry Andric     }
4400b57cec5SDimitry Andric     std::string Init = UseShared
4410b57cec5SDimitry Andric           ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
4420b57cec5SDimitry Andric           : Find(RootDir, StartSubDir, "/init.o");
4430b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Init));
4440b57cec5SDimitry Andric   }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4470b57cec5SDimitry Andric   // Library Search Paths
4480b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4490b57cec5SDimitry Andric   const ToolChain::path_list &LibPaths = HTC.getFilePaths();
4500b57cec5SDimitry Andric   for (const auto &LibPath : LibPaths)
4510b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
4528a4dda33SDimitry Andric   Args.ClaimAllArgs(options::OPT_L);
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4550b57cec5SDimitry Andric   //
4560b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4575f757f3fSDimitry Andric   Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
4580b57cec5SDimitry Andric                             options::OPT_t, options::OPT_u_Group});
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4630b57cec5SDimitry Andric   // Libraries
4640b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4650b57cec5SDimitry Andric   if (IncStdLib && IncDefLibs) {
4660b57cec5SDimitry Andric     if (D.CCCIsCXX()) {
4670b57cec5SDimitry Andric       if (HTC.ShouldLinkCXXStdlib(Args))
4680b57cec5SDimitry Andric         HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
4690b57cec5SDimitry Andric       CmdArgs.push_back("-lm");
4700b57cec5SDimitry Andric     }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric     CmdArgs.push_back("--start-group");
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric     if (!IsShared) {
4750b57cec5SDimitry Andric       for (StringRef Lib : OsLibs)
4760b57cec5SDimitry Andric         CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
4775f757f3fSDimitry Andric       if (!Args.hasArg(options::OPT_nolibc))
4780b57cec5SDimitry Andric         CmdArgs.push_back("-lc");
4790b57cec5SDimitry Andric     }
4800b57cec5SDimitry Andric     CmdArgs.push_back("-lgcc");
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric     CmdArgs.push_back("--end-group");
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4860b57cec5SDimitry Andric   // End files
4870b57cec5SDimitry Andric   //----------------------------------------------------------------------------
4880b57cec5SDimitry Andric   if (IncStdLib && IncStartFiles) {
4890b57cec5SDimitry Andric     std::string Fini = UseShared
4900b57cec5SDimitry Andric           ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
4910b57cec5SDimitry Andric           : Find(RootDir, StartSubDir, "/fini.o");
4920b57cec5SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(Fini));
4930b57cec5SDimitry Andric   }
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
4970b57cec5SDimitry Andric                                    const InputInfo &Output,
4980b57cec5SDimitry Andric                                    const InputInfoList &Inputs,
4990b57cec5SDimitry Andric                                    const ArgList &Args,
5000b57cec5SDimitry Andric                                    const char *LinkingOutput) const {
5010b57cec5SDimitry Andric   auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   ArgStringList CmdArgs;
5040b57cec5SDimitry Andric   constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
5050b57cec5SDimitry Andric                            LinkingOutput);
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
508e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(JA, *this,
509e8d8bef9SDimitry Andric                                          ResponseFileSupport::AtFileCurCP(),
510e8d8bef9SDimitry Andric                                          Exec, CmdArgs, Inputs, Output));
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric // Hexagon tools end.
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric /// Hexagon Toolchain
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric std::string HexagonToolChain::getHexagonTargetDir(
5170b57cec5SDimitry Andric       const std::string &InstalledDir,
5180b57cec5SDimitry Andric       const SmallVectorImpl<std::string> &PrefixDirs) const {
5190b57cec5SDimitry Andric   std::string InstallRelDir;
5200b57cec5SDimitry Andric   const Driver &D = getDriver();
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   // Locate the rest of the toolchain ...
5230b57cec5SDimitry Andric   for (auto &I : PrefixDirs)
5240b57cec5SDimitry Andric     if (D.getVFS().exists(I))
5250b57cec5SDimitry Andric       return I;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
5280b57cec5SDimitry Andric     return InstallRelDir;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   return InstalledDir;
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric 
533bdd1243dSDimitry Andric std::optional<unsigned>
534bdd1243dSDimitry Andric HexagonToolChain::getSmallDataThreshold(const ArgList &Args) {
5350b57cec5SDimitry Andric   StringRef Gn = "";
5360b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_G)) {
5370b57cec5SDimitry Andric     Gn = A->getValue();
5380b57cec5SDimitry Andric   } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
5390b57cec5SDimitry Andric                              options::OPT_fPIC)) {
5400b57cec5SDimitry Andric     Gn = "0";
5410b57cec5SDimitry Andric   }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   unsigned G;
5440b57cec5SDimitry Andric   if (!Gn.getAsInteger(10, G))
5450b57cec5SDimitry Andric     return G;
5460b57cec5SDimitry Andric 
547bdd1243dSDimitry Andric   return std::nullopt;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
550349cc55cSDimitry Andric std::string HexagonToolChain::getCompilerRTPath() const {
551349cc55cSDimitry Andric   SmallString<128> Dir(getDriver().SysRoot);
552349cc55cSDimitry Andric   llvm::sys::path::append(Dir, "usr", "lib");
55306c3fb27SDimitry Andric   if (!SelectedMultilibs.empty()) {
55406c3fb27SDimitry Andric     Dir += SelectedMultilibs.back().gccSuffix();
55506c3fb27SDimitry Andric   }
5567a6dacacSDimitry Andric   return std::string(Dir);
557349cc55cSDimitry Andric }
558349cc55cSDimitry Andric 
5590b57cec5SDimitry Andric void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
5600b57cec5SDimitry Andric       ToolChain::path_list &LibPaths) const {
5610b57cec5SDimitry Andric   const Driver &D = getDriver();
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   //----------------------------------------------------------------------------
5640b57cec5SDimitry Andric   // -L Args
5650b57cec5SDimitry Andric   //----------------------------------------------------------------------------
5660b57cec5SDimitry Andric   for (Arg *A : Args.filtered(options::OPT_L))
56781ad6265SDimitry Andric     llvm::append_range(LibPaths, A->getValues());
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   //----------------------------------------------------------------------------
5700b57cec5SDimitry Andric   // Other standard paths
5710b57cec5SDimitry Andric   //----------------------------------------------------------------------------
5720b57cec5SDimitry Andric   std::vector<std::string> RootDirs;
5730b57cec5SDimitry Andric   std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
5740b57cec5SDimitry Andric             std::back_inserter(RootDirs));
5750b57cec5SDimitry Andric 
5760fca6ea1SDimitry Andric   std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
577349cc55cSDimitry Andric   if (!llvm::is_contained(RootDirs, TargetDir))
5780b57cec5SDimitry Andric     RootDirs.push_back(TargetDir);
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
5810b57cec5SDimitry Andric   // Assume G0 with -shared.
5820b57cec5SDimitry Andric   bool HasG0 = Args.hasArg(options::OPT_shared);
5830b57cec5SDimitry Andric   if (auto G = getSmallDataThreshold(Args))
58481ad6265SDimitry Andric     HasG0 = *G == 0;
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   const std::string CpuVer = GetTargetCPUVersion(Args).str();
5870b57cec5SDimitry Andric   for (auto &Dir : RootDirs) {
5880b57cec5SDimitry Andric     std::string LibDir = Dir + "/hexagon/lib";
5890b57cec5SDimitry Andric     std::string LibDirCpu = LibDir + '/' + CpuVer;
5900b57cec5SDimitry Andric     if (HasG0) {
5910b57cec5SDimitry Andric       if (HasPIC)
5920b57cec5SDimitry Andric         LibPaths.push_back(LibDirCpu + "/G0/pic");
5930b57cec5SDimitry Andric       LibPaths.push_back(LibDirCpu + "/G0");
5940b57cec5SDimitry Andric     }
5950b57cec5SDimitry Andric     LibPaths.push_back(LibDirCpu);
5960b57cec5SDimitry Andric     LibPaths.push_back(LibDir);
5970b57cec5SDimitry Andric   }
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
6010b57cec5SDimitry Andric                                    const llvm::opt::ArgList &Args)
6020b57cec5SDimitry Andric     : Linux(D, Triple, Args) {
6030fca6ea1SDimitry Andric   const std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
6060b57cec5SDimitry Andric   // program paths
6070b57cec5SDimitry Andric   const std::string BinDir(TargetDir + "/bin");
6080b57cec5SDimitry Andric   if (D.getVFS().exists(BinDir))
6090b57cec5SDimitry Andric     getProgramPaths().push_back(BinDir);
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   ToolChain::path_list &LibPaths = getFilePaths();
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
6140b57cec5SDimitry Andric   // 'elf' OS type, so the Linux paths are not appropriate. When we actually
6150b57cec5SDimitry Andric   // support 'linux' we'll need to fix this up
6160b57cec5SDimitry Andric   LibPaths.clear();
6170b57cec5SDimitry Andric   getHexagonLibraryPaths(Args, LibPaths);
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric HexagonToolChain::~HexagonToolChain() {}
6210b57cec5SDimitry Andric 
6225ffd83dbSDimitry Andric void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
6235ffd83dbSDimitry Andric                                            ArgStringList &CmdArgs) const {
6245ffd83dbSDimitry Andric   CXXStdlibType Type = GetCXXStdlibType(Args);
6250fca6ea1SDimitry Andric   ToolChain::UnwindLibType UNW = GetUnwindLibType(Args);
6260fca6ea1SDimitry Andric   if (UNW != ToolChain::UNW_None && UNW != ToolChain::UNW_CompilerRT) {
6270fca6ea1SDimitry Andric     const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
6280fca6ea1SDimitry Andric     if (A) {
6290fca6ea1SDimitry Andric       getDriver().Diag(diag::err_drv_unsupported_unwind_for_platform)
6300fca6ea1SDimitry Andric           << A->getValue() << getTriple().normalize();
6310fca6ea1SDimitry Andric       return;
6320fca6ea1SDimitry Andric     }
6330fca6ea1SDimitry Andric   }
6340fca6ea1SDimitry Andric 
6355ffd83dbSDimitry Andric   switch (Type) {
6365ffd83dbSDimitry Andric   case ToolChain::CST_Libcxx:
6375ffd83dbSDimitry Andric     CmdArgs.push_back("-lc++");
638fcaf7f86SDimitry Andric     if (Args.hasArg(options::OPT_fexperimental_library))
639fcaf7f86SDimitry Andric       CmdArgs.push_back("-lc++experimental");
6405ffd83dbSDimitry Andric     CmdArgs.push_back("-lc++abi");
6410fca6ea1SDimitry Andric     if (UNW != ToolChain::UNW_None)
6425ffd83dbSDimitry Andric       CmdArgs.push_back("-lunwind");
6435ffd83dbSDimitry Andric     break;
6445ffd83dbSDimitry Andric 
6455ffd83dbSDimitry Andric   case ToolChain::CST_Libstdcxx:
6465ffd83dbSDimitry Andric     CmdArgs.push_back("-lstdc++");
6475ffd83dbSDimitry Andric     break;
6485ffd83dbSDimitry Andric   }
6495ffd83dbSDimitry Andric }
6505ffd83dbSDimitry Andric 
6510b57cec5SDimitry Andric Tool *HexagonToolChain::buildAssembler() const {
6520b57cec5SDimitry Andric   return new tools::hexagon::Assembler(*this);
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric Tool *HexagonToolChain::buildLinker() const {
6560b57cec5SDimitry Andric   return new tools::hexagon::Linker(*this);
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric unsigned HexagonToolChain::getOptimizationLevel(
6600b57cec5SDimitry Andric     const llvm::opt::ArgList &DriverArgs) const {
6610b57cec5SDimitry Andric   // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
6620b57cec5SDimitry Andric   Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
6630b57cec5SDimitry Andric   if (!A)
6640b57cec5SDimitry Andric     return 0;
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   if (A->getOption().matches(options::OPT_O0))
6670b57cec5SDimitry Andric     return 0;
6680b57cec5SDimitry Andric   if (A->getOption().matches(options::OPT_Ofast) ||
6690b57cec5SDimitry Andric       A->getOption().matches(options::OPT_O4))
6700b57cec5SDimitry Andric     return 3;
6710b57cec5SDimitry Andric   assert(A->getNumValues() != 0);
6720b57cec5SDimitry Andric   StringRef S(A->getValue());
6730b57cec5SDimitry Andric   if (S == "s" || S == "z" || S.empty())
6740b57cec5SDimitry Andric     return 2;
6750b57cec5SDimitry Andric   if (S == "g")
6760b57cec5SDimitry Andric     return 1;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   unsigned OptLevel;
6790b57cec5SDimitry Andric   if (S.getAsInteger(10, OptLevel))
6800b57cec5SDimitry Andric     return 0;
6810b57cec5SDimitry Andric   return OptLevel;
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
6850b57cec5SDimitry Andric                                              ArgStringList &CC1Args,
6860b57cec5SDimitry Andric                                              Action::OffloadKind) const {
6875ffd83dbSDimitry Andric 
6885ffd83dbSDimitry Andric   bool UseInitArrayDefault = getTriple().isMusl();
6895ffd83dbSDimitry Andric 
6905ffd83dbSDimitry Andric   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
6915ffd83dbSDimitry Andric                           options::OPT_fno_use_init_array,
6925ffd83dbSDimitry Andric                           UseInitArrayDefault))
6935ffd83dbSDimitry Andric     CC1Args.push_back("-fno-use-init-array");
6945ffd83dbSDimitry Andric 
6950b57cec5SDimitry Andric   if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
6960b57cec5SDimitry Andric     CC1Args.push_back("-target-feature");
6970b57cec5SDimitry Andric     CC1Args.push_back("+reserved-r19");
6980b57cec5SDimitry Andric   }
6990b57cec5SDimitry Andric   if (isAutoHVXEnabled(DriverArgs)) {
7000b57cec5SDimitry Andric     CC1Args.push_back("-mllvm");
7010b57cec5SDimitry Andric     CC1Args.push_back("-hexagon-autohvx");
7020b57cec5SDimitry Andric   }
7030b57cec5SDimitry Andric }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
7060b57cec5SDimitry Andric                                                  ArgStringList &CC1Args) const {
7076e75b2fbSDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc))
7080b57cec5SDimitry Andric     return;
7090b57cec5SDimitry Andric 
7106e75b2fbSDimitry Andric   const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();
7116e75b2fbSDimitry Andric   const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();
7126e75b2fbSDimitry Andric 
7130b57cec5SDimitry Andric   const Driver &D = getDriver();
7146e75b2fbSDimitry Andric   SmallString<128> ResourceDirInclude(D.ResourceDir);
7156e75b2fbSDimitry Andric   if (!IsELF) {
7166e75b2fbSDimitry Andric     llvm::sys::path::append(ResourceDirInclude, "include");
7176e75b2fbSDimitry Andric     if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&
7186e75b2fbSDimitry Andric         (!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))
7196e75b2fbSDimitry Andric       addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
7206e75b2fbSDimitry Andric   }
7216e75b2fbSDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
7226e75b2fbSDimitry Andric     return;
7236e75b2fbSDimitry Andric 
7246e75b2fbSDimitry Andric   const bool HasSysRoot = !D.SysRoot.empty();
7256e75b2fbSDimitry Andric   if (HasSysRoot) {
7265ffd83dbSDimitry Andric     SmallString<128> P(D.SysRoot);
7276e75b2fbSDimitry Andric     if (IsLinuxMusl)
7285ffd83dbSDimitry Andric       llvm::sys::path::append(P, "usr/include");
7295ffd83dbSDimitry Andric     else
7305ffd83dbSDimitry Andric       llvm::sys::path::append(P, "include");
7316e75b2fbSDimitry Andric 
7325ffd83dbSDimitry Andric     addExternCSystemInclude(DriverArgs, CC1Args, P.str());
7336e75b2fbSDimitry Andric     // LOCAL_INCLUDE_DIR
7346e75b2fbSDimitry Andric     addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");
7356e75b2fbSDimitry Andric     // TOOL_INCLUDE_DIR
7366e75b2fbSDimitry Andric     AddMultilibIncludeArgs(DriverArgs, CC1Args);
7375ffd83dbSDimitry Andric   }
7385ffd83dbSDimitry Andric 
7396e75b2fbSDimitry Andric   if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)
7406e75b2fbSDimitry Andric     addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
7416e75b2fbSDimitry Andric 
7426e75b2fbSDimitry Andric   if (HasSysRoot)
7436e75b2fbSDimitry Andric     return;
7440fca6ea1SDimitry Andric   std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
7450b57cec5SDimitry Andric   addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
7460b57cec5SDimitry Andric }
7470b57cec5SDimitry Andric 
7485ffd83dbSDimitry Andric void HexagonToolChain::addLibCxxIncludePaths(
7495ffd83dbSDimitry Andric     const llvm::opt::ArgList &DriverArgs,
7505ffd83dbSDimitry Andric     llvm::opt::ArgStringList &CC1Args) const {
7515ffd83dbSDimitry Andric   const Driver &D = getDriver();
7525ffd83dbSDimitry Andric   if (!D.SysRoot.empty() && getTriple().isMusl())
753fe6060f1SDimitry Andric     addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",
7545ffd83dbSDimitry Andric                              DriverArgs, CC1Args);
755fe6060f1SDimitry Andric   else if (getTriple().isMusl())
756fe6060f1SDimitry Andric     addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
757fe6060f1SDimitry Andric                              CC1Args);
7585ffd83dbSDimitry Andric   else {
7590fca6ea1SDimitry Andric     std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
760fe6060f1SDimitry Andric     addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
761fe6060f1SDimitry Andric                              DriverArgs, CC1Args);
7625ffd83dbSDimitry Andric   }
7635ffd83dbSDimitry Andric }
7640b57cec5SDimitry Andric void HexagonToolChain::addLibStdCxxIncludePaths(
7650b57cec5SDimitry Andric     const llvm::opt::ArgList &DriverArgs,
7660b57cec5SDimitry Andric     llvm::opt::ArgStringList &CC1Args) const {
7670b57cec5SDimitry Andric   const Driver &D = getDriver();
7680fca6ea1SDimitry Andric   std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
769fe6060f1SDimitry Andric   addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
7700b57cec5SDimitry Andric                            DriverArgs, CC1Args);
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric ToolChain::CXXStdlibType
7740b57cec5SDimitry Andric HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
7750b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
7765ffd83dbSDimitry Andric   if (!A) {
7775ffd83dbSDimitry Andric     if (getTriple().isMusl())
7785ffd83dbSDimitry Andric       return ToolChain::CST_Libcxx;
7795ffd83dbSDimitry Andric     else
7800b57cec5SDimitry Andric       return ToolChain::CST_Libstdcxx;
7815ffd83dbSDimitry Andric   }
7820b57cec5SDimitry Andric   StringRef Value = A->getValue();
7835ffd83dbSDimitry Andric   if (Value != "libstdc++" && Value != "libc++")
7840b57cec5SDimitry Andric     getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
7850b57cec5SDimitry Andric 
7865ffd83dbSDimitry Andric   if (Value == "libstdc++")
7875ffd83dbSDimitry Andric     return ToolChain::CST_Libstdcxx;
7885ffd83dbSDimitry Andric   else if (Value == "libc++")
7895ffd83dbSDimitry Andric     return ToolChain::CST_Libcxx;
7905ffd83dbSDimitry Andric   else
7910b57cec5SDimitry Andric     return ToolChain::CST_Libstdcxx;
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
7950b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
7960b57cec5SDimitry Andric                                options::OPT_fno_vectorize))
7970b57cec5SDimitry Andric     return A->getOption().matches(options::OPT_fvectorize);
7980b57cec5SDimitry Andric   return false;
7990b57cec5SDimitry Andric }
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric //
8020b57cec5SDimitry Andric // Returns the default CPU for Hexagon. This is the default compilation target
8030b57cec5SDimitry Andric // if no Hexagon processor is selected at the command-line.
8040b57cec5SDimitry Andric //
805349cc55cSDimitry Andric StringRef HexagonToolChain::GetDefaultCPU() {
8060b57cec5SDimitry Andric   return "hexagonv60";
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric 
809349cc55cSDimitry Andric StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
8100b57cec5SDimitry Andric   Arg *CpuArg = nullptr;
811480093f4SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
8120b57cec5SDimitry Andric     CpuArg = A;
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
8150fca6ea1SDimitry Andric   CPU.consume_front("hexagon");
8160b57cec5SDimitry Andric   return CPU;
8170b57cec5SDimitry Andric }
818