123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- //===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "Hexagon.h"
- #include "CommonArgs.h"
- #include "clang/Driver/Compilation.h"
- #include "clang/Driver/Driver.h"
- #include "clang/Driver/DriverDiagnostic.h"
- #include "clang/Driver/InputInfo.h"
- #include "clang/Driver/Options.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/Option/ArgList.h"
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/VirtualFileSystem.h"
- using namespace clang::driver;
- using namespace clang::driver::tools;
- using namespace clang::driver::toolchains;
- using namespace clang;
- using namespace llvm::opt;
- // Default hvx-length for various versions.
- static StringRef getDefaultHvxLength(StringRef HvxVer) {
- return llvm::StringSwitch<StringRef>(HvxVer)
- .Case("v60", "64b")
- .Case("v62", "64b")
- .Case("v65", "64b")
- .Default("128b");
- }
- static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
- // Handle the unsupported values passed to mhvx-length.
- if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
- StringRef Val = A->getValue();
- if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
- }
- }
- // Handle hvx target features explicitly.
- static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<StringRef> &Features,
- StringRef Cpu, bool &HasHVX) {
- // Handle HVX warnings.
- handleHVXWarnings(D, Args);
- auto makeFeature = [&Args](Twine T, bool Enable) -> StringRef {
- const std::string &S = T.str();
- StringRef Opt(S);
- if (Opt.endswith("="))
- Opt = Opt.drop_back(1);
- if (Opt.startswith("mno-"))
- Opt = Opt.drop_front(4);
- else if (Opt.startswith("m"))
- Opt = Opt.drop_front(1);
- return Args.MakeArgString(Twine(Enable ? "+" : "-") + Twine(Opt));
- };
- auto withMinus = [](StringRef S) -> std::string {
- return "-" + S.str();
- };
- // Drop tiny core suffix for HVX version.
- std::string HvxVer =
- (Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();
- HasHVX = false;
- // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags
- // are both present, the last one wins.
- Arg *HvxEnablingArg =
- Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,
- options::OPT_mno_hexagon_hvx);
- if (HvxEnablingArg) {
- if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))
- HvxEnablingArg = nullptr;
- }
- if (HvxEnablingArg) {
- // If -mhvx[=] was given, it takes precedence.
- if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,
- options::OPT_mhexagon_hvx_EQ)) {
- // If the version was given, set HvxVer. Otherwise HvxVer
- // will remain equal to the CPU version.
- if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))
- HvxVer = StringRef(A->getValue()).lower();
- }
- HasHVX = true;
- Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));
- } else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {
- // If there was an explicit -mno-hvx, add -hvx to target features.
- Features.push_back(makeFeature(A->getOption().getName(), false));
- }
- StringRef HvxLen = getDefaultHvxLength(HvxVer);
- // Handle -mhvx-length=.
- if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
- // These flags are valid only if HVX in enabled.
- if (!HasHVX)
- D.Diag(diag::err_drv_needs_hvx) << withMinus(A->getOption().getName());
- else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
- HvxLen = A->getValue();
- }
- if (HasHVX) {
- StringRef L = makeFeature(Twine("hvx-length") + HvxLen.lower(), true);
- Features.push_back(L);
- }
- unsigned HvxVerNum;
- // getAsInteger returns 'true' on error.
- if (StringRef(HvxVer).drop_front(1).getAsInteger(10, HvxVerNum))
- HvxVerNum = 0;
- // Handle HVX floating point flags.
- auto checkFlagHvxVersion = [&](auto FlagOn, auto FlagOff,
- unsigned MinVerNum) -> Optional<StringRef> {
- // Return an Optional<StringRef>:
- // - None indicates a verification failure, or that the flag was not
- // present in Args.
- // - Otherwise the returned value is that name of the feature to add
- // to Features.
- Arg *A = Args.getLastArg(FlagOn, FlagOff);
- if (!A)
- return None;
- StringRef OptName = A->getOption().getName();
- if (A->getOption().matches(FlagOff))
- return makeFeature(OptName, false);
- if (!HasHVX) {
- D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);
- return None;
- }
- if (HvxVerNum < MinVerNum) {
- D.Diag(diag::err_drv_needs_hvx_version)
- << withMinus(OptName) << ("v" + std::to_string(HvxVerNum));
- return None;
- }
- return makeFeature(OptName, true);
- };
- if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,
- options::OPT_mno_hexagon_hvx_qfloat, 68)) {
- Features.push_back(*F);
- }
- if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,
- options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {
- Features.push_back(*F);
- }
- }
- // Hexagon target features.
- void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<StringRef> &Features) {
- handleTargetFeaturesGroup(Args, Features,
- options::OPT_m_hexagon_Features_Group);
- bool UseLongCalls = false;
- if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
- options::OPT_mno_long_calls)) {
- if (A->getOption().matches(options::OPT_mlong_calls))
- UseLongCalls = true;
- }
- Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
- bool HasHVX = false;
- StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
- // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
- // have no dependency on micro-architecture.
- const bool TinyCore = Cpu.contains('t');
- if (TinyCore)
- Cpu = Cpu.take_front(Cpu.size() - 1);
- handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
- if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
- D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";
- }
- // Hexagon tools start.
- void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
- }
- void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
- auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
- const Driver &D = HTC.getDriver();
- ArgStringList CmdArgs;
- CmdArgs.push_back("--arch=hexagon");
- RenderExtraToolArgs(JA, CmdArgs);
- const char *AsName = "llvm-mc";
- CmdArgs.push_back("-filetype=obj");
- CmdArgs.push_back(Args.MakeArgString(
- "-mcpu=hexagon" +
- toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
- addSanitizerRuntimes(HTC, Args, CmdArgs);
- if (Output.isFilename()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Unexpected output");
- CmdArgs.push_back("-fsyntax-only");
- }
- if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,
- options::OPT_mno_hexagon_hvx_ieee_fp)) {
- if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))
- CmdArgs.push_back("-mhvx-ieee-fp");
- }
- if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
- CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
- }
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
- // Only pass -x if gcc will understand it; otherwise hope gcc
- // understands the suffix correctly. The main use case this would go
- // wrong in is for linker inputs if they happened to have an odd
- // suffix; really the only way to get this to happen is a command
- // like '-x foobar a.c' which will treat a.c like a linker input.
- //
- // FIXME: For the linker case specifically, can we safely convert
- // inputs into '-Wl,' options?
- for (const auto &II : Inputs) {
- // Don't try to pass LLVM or AST inputs to a generic gcc.
- if (types::isLLVMIR(II.getType()))
- D.Diag(clang::diag::err_drv_no_linker_llvm_support)
- << HTC.getTripleString();
- else if (II.getType() == types::TY_AST)
- D.Diag(clang::diag::err_drv_no_ast_support)
- << HTC.getTripleString();
- else if (II.getType() == types::TY_ModuleFile)
- D.Diag(diag::err_drv_no_module_support)
- << HTC.getTripleString();
- if (II.isFilename())
- CmdArgs.push_back(II.getFilename());
- else
- // Don't render as input, we need gcc to do the translations.
- // FIXME: What is this?
- II.getInputArg().render(Args, CmdArgs);
- }
- auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
- }
- void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
- ArgStringList &CmdArgs) const {
- }
- static void
- constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
- const toolchains::HexagonToolChain &HTC,
- const InputInfo &Output, const InputInfoList &Inputs,
- const ArgList &Args, ArgStringList &CmdArgs,
- const char *LinkingOutput) {
- const Driver &D = HTC.getDriver();
- //----------------------------------------------------------------------------
- //
- //----------------------------------------------------------------------------
- bool IsStatic = Args.hasArg(options::OPT_static);
- bool IsShared = Args.hasArg(options::OPT_shared);
- bool IsPIE = Args.hasArg(options::OPT_pie);
- bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
- bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
- bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
- bool UseG0 = false;
- const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
- bool UseLLD = (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") ||
- llvm::sys::path::stem(Exec).equals_insensitive("ld.lld"));
- bool UseShared = IsShared && !IsStatic;
- StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
- bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
- //----------------------------------------------------------------------------
- // Silence warnings for various options
- //----------------------------------------------------------------------------
- Args.ClaimAllArgs(options::OPT_g_Group);
- Args.ClaimAllArgs(options::OPT_emit_llvm);
- Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
- // handled somewhere else.
- Args.ClaimAllArgs(options::OPT_static_libgcc);
- //----------------------------------------------------------------------------
- //
- //----------------------------------------------------------------------------
- if (Args.hasArg(options::OPT_s))
- CmdArgs.push_back("-s");
- if (Args.hasArg(options::OPT_r))
- CmdArgs.push_back("-r");
- for (const auto &Opt : HTC.ExtraOpts)
- CmdArgs.push_back(Opt.c_str());
- if (!UseLLD) {
- CmdArgs.push_back("-march=hexagon");
- CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
- }
- if (IsShared) {
- CmdArgs.push_back("-shared");
- // The following should be the default, but doing as hexagon-gcc does.
- CmdArgs.push_back("-call_shared");
- }
- if (IsStatic)
- CmdArgs.push_back("-static");
- if (IsPIE && !IsShared)
- CmdArgs.push_back("-pie");
- if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
- CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
- UseG0 = G.getValue() == 0;
- }
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- if (HTC.getTriple().isMusl()) {
- if (!Args.hasArg(options::OPT_shared, options::OPT_static))
- CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
- if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
- options::OPT_nostdlib))
- CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
- else if (Args.hasArg(options::OPT_shared) &&
- !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
- CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
- CmdArgs.push_back(
- Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_u_Group});
- AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (NeedsSanitizerDeps) {
- linkSanitizerRuntimeDeps(HTC, CmdArgs);
- CmdArgs.push_back("-lunwind");
- }
- if (NeedsXRayDeps)
- linkXRayRuntimeDeps(HTC, CmdArgs);
- CmdArgs.push_back("-lclang_rt.builtins-hexagon");
- CmdArgs.push_back("-lc");
- }
- if (D.CCCIsCXX()) {
- if (HTC.ShouldLinkCXXStdlib(Args))
- HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
- }
- return;
- }
- //----------------------------------------------------------------------------
- // moslib
- //----------------------------------------------------------------------------
- std::vector<std::string> OsLibs;
- bool HasStandalone = false;
- for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
- A->claim();
- OsLibs.emplace_back(A->getValue());
- HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
- }
- if (OsLibs.empty()) {
- OsLibs.push_back("standalone");
- HasStandalone = true;
- }
- //----------------------------------------------------------------------------
- // Start Files
- //----------------------------------------------------------------------------
- const std::string MCpuSuffix = "/" + CpuVer.str();
- const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
- const std::string RootDir =
- HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
- const std::string StartSubDir =
- "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
- auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
- const char *Name) -> std::string {
- std::string RelName = SubDir + Name;
- std::string P = HTC.GetFilePath(RelName.c_str());
- if (llvm::sys::fs::exists(P))
- return P;
- return RootDir + RelName;
- };
- if (IncStdLib && IncStartFiles) {
- if (!IsShared) {
- if (HasStandalone) {
- std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
- CmdArgs.push_back(Args.MakeArgString(Crt0SA));
- }
- std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
- CmdArgs.push_back(Args.MakeArgString(Crt0));
- }
- std::string Init = UseShared
- ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
- : Find(RootDir, StartSubDir, "/init.o");
- CmdArgs.push_back(Args.MakeArgString(Init));
- }
- //----------------------------------------------------------------------------
- // Library Search Paths
- //----------------------------------------------------------------------------
- const ToolChain::path_list &LibPaths = HTC.getFilePaths();
- for (const auto &LibPath : LibPaths)
- CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
- //----------------------------------------------------------------------------
- //
- //----------------------------------------------------------------------------
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_u_Group});
- AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
- //----------------------------------------------------------------------------
- // Libraries
- //----------------------------------------------------------------------------
- if (IncStdLib && IncDefLibs) {
- if (D.CCCIsCXX()) {
- if (HTC.ShouldLinkCXXStdlib(Args))
- HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
- CmdArgs.push_back("-lm");
- }
- CmdArgs.push_back("--start-group");
- if (!IsShared) {
- for (StringRef Lib : OsLibs)
- CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
- CmdArgs.push_back("-lc");
- }
- CmdArgs.push_back("-lgcc");
- CmdArgs.push_back("--end-group");
- }
- //----------------------------------------------------------------------------
- // End files
- //----------------------------------------------------------------------------
- if (IncStdLib && IncStartFiles) {
- std::string Fini = UseShared
- ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
- : Find(RootDir, StartSubDir, "/fini.o");
- CmdArgs.push_back(Args.MakeArgString(Fini));
- }
- }
- void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
- ArgStringList CmdArgs;
- constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
- LinkingOutput);
- const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
- }
- // Hexagon tools end.
- /// Hexagon Toolchain
- std::string HexagonToolChain::getHexagonTargetDir(
- const std::string &InstalledDir,
- const SmallVectorImpl<std::string> &PrefixDirs) const {
- std::string InstallRelDir;
- const Driver &D = getDriver();
- // Locate the rest of the toolchain ...
- for (auto &I : PrefixDirs)
- if (D.getVFS().exists(I))
- return I;
- if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
- return InstallRelDir;
- return InstalledDir;
- }
- Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
- const ArgList &Args) {
- StringRef Gn = "";
- if (Arg *A = Args.getLastArg(options::OPT_G)) {
- Gn = A->getValue();
- } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
- options::OPT_fPIC)) {
- Gn = "0";
- }
- unsigned G;
- if (!Gn.getAsInteger(10, G))
- return G;
- return None;
- }
- std::string HexagonToolChain::getCompilerRTPath() const {
- SmallString<128> Dir(getDriver().SysRoot);
- llvm::sys::path::append(Dir, "usr", "lib");
- Dir += SelectedMultilib.gccSuffix();
- return std::string(Dir.str());
- }
- void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
- ToolChain::path_list &LibPaths) const {
- const Driver &D = getDriver();
- //----------------------------------------------------------------------------
- // -L Args
- //----------------------------------------------------------------------------
- for (Arg *A : Args.filtered(options::OPT_L))
- for (const char *Value : A->getValues())
- LibPaths.push_back(Value);
- //----------------------------------------------------------------------------
- // Other standard paths
- //----------------------------------------------------------------------------
- std::vector<std::string> RootDirs;
- std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
- std::back_inserter(RootDirs));
- std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
- D.PrefixDirs);
- if (!llvm::is_contained(RootDirs, TargetDir))
- RootDirs.push_back(TargetDir);
- bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
- // Assume G0 with -shared.
- bool HasG0 = Args.hasArg(options::OPT_shared);
- if (auto G = getSmallDataThreshold(Args))
- HasG0 = G.getValue() == 0;
- const std::string CpuVer = GetTargetCPUVersion(Args).str();
- for (auto &Dir : RootDirs) {
- std::string LibDir = Dir + "/hexagon/lib";
- std::string LibDirCpu = LibDir + '/' + CpuVer;
- if (HasG0) {
- if (HasPIC)
- LibPaths.push_back(LibDirCpu + "/G0/pic");
- LibPaths.push_back(LibDirCpu + "/G0");
- }
- LibPaths.push_back(LibDirCpu);
- LibPaths.push_back(LibDir);
- }
- }
- HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args)
- : Linux(D, Triple, Args) {
- const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
- D.PrefixDirs);
- // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
- // program paths
- const std::string BinDir(TargetDir + "/bin");
- if (D.getVFS().exists(BinDir))
- getProgramPaths().push_back(BinDir);
- ToolChain::path_list &LibPaths = getFilePaths();
- // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
- // 'elf' OS type, so the Linux paths are not appropriate. When we actually
- // support 'linux' we'll need to fix this up
- LibPaths.clear();
- getHexagonLibraryPaths(Args, LibPaths);
- }
- HexagonToolChain::~HexagonToolChain() {}
- void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- CXXStdlibType Type = GetCXXStdlibType(Args);
- switch (Type) {
- case ToolChain::CST_Libcxx:
- CmdArgs.push_back("-lc++");
- CmdArgs.push_back("-lc++abi");
- CmdArgs.push_back("-lunwind");
- break;
- case ToolChain::CST_Libstdcxx:
- CmdArgs.push_back("-lstdc++");
- break;
- }
- }
- Tool *HexagonToolChain::buildAssembler() const {
- return new tools::hexagon::Assembler(*this);
- }
- Tool *HexagonToolChain::buildLinker() const {
- return new tools::hexagon::Linker(*this);
- }
- unsigned HexagonToolChain::getOptimizationLevel(
- const llvm::opt::ArgList &DriverArgs) const {
- // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
- Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
- if (!A)
- return 0;
- if (A->getOption().matches(options::OPT_O0))
- return 0;
- if (A->getOption().matches(options::OPT_Ofast) ||
- A->getOption().matches(options::OPT_O4))
- return 3;
- assert(A->getNumValues() != 0);
- StringRef S(A->getValue());
- if (S == "s" || S == "z" || S.empty())
- return 2;
- if (S == "g")
- return 1;
- unsigned OptLevel;
- if (S.getAsInteger(10, OptLevel))
- return 0;
- return OptLevel;
- }
- void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
- Action::OffloadKind) const {
- bool UseInitArrayDefault = getTriple().isMusl();
- if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array,
- UseInitArrayDefault))
- CC1Args.push_back("-fno-use-init-array");
- if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
- CC1Args.push_back("-target-feature");
- CC1Args.push_back("+reserved-r19");
- }
- if (isAutoHVXEnabled(DriverArgs)) {
- CC1Args.push_back("-mllvm");
- CC1Args.push_back("-hexagon-autohvx");
- }
- }
- void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdinc))
- return;
- const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();
- const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();
- const Driver &D = getDriver();
- SmallString<128> ResourceDirInclude(D.ResourceDir);
- if (!IsELF) {
- llvm::sys::path::append(ResourceDirInclude, "include");
- if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&
- (!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))
- addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
- }
- if (DriverArgs.hasArg(options::OPT_nostdlibinc))
- return;
- const bool HasSysRoot = !D.SysRoot.empty();
- if (HasSysRoot) {
- SmallString<128> P(D.SysRoot);
- if (IsLinuxMusl)
- llvm::sys::path::append(P, "usr/include");
- else
- llvm::sys::path::append(P, "include");
- addExternCSystemInclude(DriverArgs, CC1Args, P.str());
- // LOCAL_INCLUDE_DIR
- addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");
- // TOOL_INCLUDE_DIR
- AddMultilibIncludeArgs(DriverArgs, CC1Args);
- }
- if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)
- addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
- if (HasSysRoot)
- return;
- std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
- D.PrefixDirs);
- addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
- }
- void HexagonToolChain::addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- const Driver &D = getDriver();
- if (!D.SysRoot.empty() && getTriple().isMusl())
- addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",
- DriverArgs, CC1Args);
- else if (getTriple().isMusl())
- addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
- CC1Args);
- else {
- std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
- addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
- DriverArgs, CC1Args);
- }
- }
- void HexagonToolChain::addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- const Driver &D = getDriver();
- std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
- addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
- DriverArgs, CC1Args);
- }
- ToolChain::CXXStdlibType
- HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
- Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
- if (!A) {
- if (getTriple().isMusl())
- return ToolChain::CST_Libcxx;
- else
- return ToolChain::CST_Libstdcxx;
- }
- StringRef Value = A->getValue();
- if (Value != "libstdc++" && Value != "libc++")
- getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
- if (Value == "libstdc++")
- return ToolChain::CST_Libstdcxx;
- else if (Value == "libc++")
- return ToolChain::CST_Libcxx;
- else
- return ToolChain::CST_Libstdcxx;
- }
- bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
- if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
- options::OPT_fno_vectorize))
- return A->getOption().matches(options::OPT_fvectorize);
- return false;
- }
- //
- // Returns the default CPU for Hexagon. This is the default compilation target
- // if no Hexagon processor is selected at the command-line.
- //
- StringRef HexagonToolChain::GetDefaultCPU() {
- return "hexagonv60";
- }
- StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
- Arg *CpuArg = nullptr;
- if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
- CpuArg = A;
- StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
- if (CPU.startswith("hexagon"))
- return CPU.substr(sizeof("hexagon") - 1);
- return CPU;
- }
|