Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
35266 views
//===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Hexagon.h"9#include "CommonArgs.h"10#include "clang/Driver/Compilation.h"11#include "clang/Driver/Driver.h"12#include "clang/Driver/DriverDiagnostic.h"13#include "clang/Driver/InputInfo.h"14#include "clang/Driver/Options.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/Option/ArgList.h"17#include "llvm/Support/FileSystem.h"18#include "llvm/Support/Path.h"19#include "llvm/Support/VirtualFileSystem.h"2021using namespace clang::driver;22using namespace clang::driver::tools;23using namespace clang::driver::toolchains;24using namespace clang;25using namespace llvm::opt;2627// Default hvx-length for various versions.28static StringRef getDefaultHvxLength(StringRef HvxVer) {29return llvm::StringSwitch<StringRef>(HvxVer)30.Case("v60", "64b")31.Case("v62", "64b")32.Case("v65", "64b")33.Default("128b");34}3536static void handleHVXWarnings(const Driver &D, const ArgList &Args) {37// Handle the unsupported values passed to mhvx-length.38if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {39StringRef Val = A->getValue();40if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))41D.Diag(diag::err_drv_unsupported_option_argument)42<< A->getSpelling() << Val;43}44}4546// Handle hvx target features explicitly.47static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,48std::vector<StringRef> &Features,49StringRef Cpu, bool &HasHVX) {50// Handle HVX warnings.51handleHVXWarnings(D, Args);5253auto makeFeature = [&Args](Twine T, bool Enable) -> StringRef {54const std::string &S = T.str();55StringRef Opt(S);56Opt.consume_back("=");57if (Opt.starts_with("mno-"))58Opt = Opt.drop_front(4);59else if (Opt.starts_with("m"))60Opt = Opt.drop_front(1);61return Args.MakeArgString(Twine(Enable ? "+" : "-") + Twine(Opt));62};6364auto withMinus = [](StringRef S) -> std::string {65return "-" + S.str();66};6768// Drop tiny core suffix for HVX version.69std::string HvxVer =70(Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();71HasHVX = false;7273// Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags74// are both present, the last one wins.75Arg *HvxEnablingArg =76Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,77options::OPT_mno_hexagon_hvx);78if (HvxEnablingArg) {79if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))80HvxEnablingArg = nullptr;81}8283if (HvxEnablingArg) {84// If -mhvx[=] was given, it takes precedence.85if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,86options::OPT_mhexagon_hvx_EQ)) {87// If the version was given, set HvxVer. Otherwise HvxVer88// will remain equal to the CPU version.89if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))90HvxVer = StringRef(A->getValue()).lower();91}92HasHVX = true;93Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));94} else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {95// If there was an explicit -mno-hvx, add -hvx to target features.96Features.push_back(makeFeature(A->getOption().getName(), false));97}9899StringRef HvxLen = getDefaultHvxLength(HvxVer);100101// Handle -mhvx-length=.102if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {103// These flags are valid only if HVX in enabled.104if (!HasHVX)105D.Diag(diag::err_drv_needs_hvx) << withMinus(A->getOption().getName());106else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))107HvxLen = A->getValue();108}109110if (HasHVX) {111StringRef L = makeFeature(Twine("hvx-length") + HvxLen.lower(), true);112Features.push_back(L);113}114115unsigned HvxVerNum;116// getAsInteger returns 'true' on error.117if (StringRef(HvxVer).drop_front(1).getAsInteger(10, HvxVerNum))118HvxVerNum = 0;119120// Handle HVX floating point flags.121auto checkFlagHvxVersion =122[&](auto FlagOn, auto FlagOff,123unsigned MinVerNum) -> std::optional<StringRef> {124// Return an std::optional<StringRef>:125// - std::nullopt indicates a verification failure, or that the flag was not126// present in Args.127// - Otherwise the returned value is that name of the feature to add128// to Features.129Arg *A = Args.getLastArg(FlagOn, FlagOff);130if (!A)131return std::nullopt;132133StringRef OptName = A->getOption().getName();134if (A->getOption().matches(FlagOff))135return makeFeature(OptName, false);136137if (!HasHVX) {138D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);139return std::nullopt;140}141if (HvxVerNum < MinVerNum) {142D.Diag(diag::err_drv_needs_hvx_version)143<< withMinus(OptName) << ("v" + std::to_string(HvxVerNum));144return std::nullopt;145}146return makeFeature(OptName, true);147};148149if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,150options::OPT_mno_hexagon_hvx_qfloat, 68)) {151Features.push_back(*F);152}153if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,154options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {155Features.push_back(*F);156}157}158159// Hexagon target features.160void hexagon::getHexagonTargetFeatures(const Driver &D,161const llvm::Triple &Triple,162const ArgList &Args,163std::vector<StringRef> &Features) {164handleTargetFeaturesGroup(D, Triple, Args, Features,165options::OPT_m_hexagon_Features_Group);166167bool UseLongCalls = false;168if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,169options::OPT_mno_long_calls)) {170if (A->getOption().matches(options::OPT_mlong_calls))171UseLongCalls = true;172}173174Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");175176bool HasHVX = false;177StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));178// 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors179// have no dependency on micro-architecture.180const bool TinyCore = Cpu.contains('t');181182if (TinyCore)183Cpu = Cpu.take_front(Cpu.size() - 1);184185handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);186187if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)188D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";189}190191// Hexagon tools start.192void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,193ArgStringList &CmdArgs) const {194}195196void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,197const InputInfo &Output,198const InputInfoList &Inputs,199const ArgList &Args,200const char *LinkingOutput) const {201claimNoWarnArgs(Args);202203auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());204const Driver &D = HTC.getDriver();205ArgStringList CmdArgs;206207CmdArgs.push_back("--arch=hexagon");208209RenderExtraToolArgs(JA, CmdArgs);210211const char *AsName = "llvm-mc";212CmdArgs.push_back("-filetype=obj");213CmdArgs.push_back(Args.MakeArgString(214"-mcpu=hexagon" +215toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));216217addSanitizerRuntimes(HTC, Args, CmdArgs);218219assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");220if (Output.isFilename()) {221CmdArgs.push_back("-o");222CmdArgs.push_back(Output.getFilename());223} else {224CmdArgs.push_back("-fsyntax-only");225}226227if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,228options::OPT_mno_hexagon_hvx_ieee_fp)) {229if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))230CmdArgs.push_back("-mhvx-ieee-fp");231}232233if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {234CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(*G)));235}236237Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);238239// Only pass -x if gcc will understand it; otherwise hope gcc240// understands the suffix correctly. The main use case this would go241// wrong in is for linker inputs if they happened to have an odd242// suffix; really the only way to get this to happen is a command243// like '-x foobar a.c' which will treat a.c like a linker input.244//245// FIXME: For the linker case specifically, can we safely convert246// inputs into '-Wl,' options?247for (const auto &II : Inputs) {248// Don't try to pass LLVM or AST inputs to a generic gcc.249if (types::isLLVMIR(II.getType()))250D.Diag(clang::diag::err_drv_no_linker_llvm_support)251<< HTC.getTripleString();252else if (II.getType() == types::TY_AST)253D.Diag(clang::diag::err_drv_no_ast_support)254<< HTC.getTripleString();255else if (II.getType() == types::TY_ModuleFile)256D.Diag(diag::err_drv_no_module_support)257<< HTC.getTripleString();258259if (II.isFilename())260CmdArgs.push_back(II.getFilename());261else262// Don't render as input, we need gcc to do the translations.263// FIXME: What is this?264II.getInputArg().render(Args, CmdArgs);265}266267auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));268C.addCommand(std::make_unique<Command>(JA, *this,269ResponseFileSupport::AtFileCurCP(),270Exec, CmdArgs, Inputs, Output));271}272273void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,274ArgStringList &CmdArgs) const {275}276277static void278constructHexagonLinkArgs(Compilation &C, const JobAction &JA,279const toolchains::HexagonToolChain &HTC,280const InputInfo &Output, const InputInfoList &Inputs,281const ArgList &Args, ArgStringList &CmdArgs,282const char *LinkingOutput) {283284const Driver &D = HTC.getDriver();285286//----------------------------------------------------------------------------287//288//----------------------------------------------------------------------------289bool IsStatic = Args.hasArg(options::OPT_static);290bool IsShared = Args.hasArg(options::OPT_shared);291bool IsPIE = Args.hasArg(options::OPT_pie);292bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);293bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);294bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);295bool UseG0 = false;296bool UseLLD = false;297const char *Exec = Args.MakeArgString(HTC.GetLinkerPath(&UseLLD));298UseLLD = UseLLD || llvm::sys::path::filename(Exec).ends_with("ld.lld") ||299llvm::sys::path::stem(Exec).ends_with("ld.lld");300bool UseShared = IsShared && !IsStatic;301StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);302303bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);304bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);305306//----------------------------------------------------------------------------307// Silence warnings for various options308//----------------------------------------------------------------------------309Args.ClaimAllArgs(options::OPT_g_Group);310Args.ClaimAllArgs(options::OPT_emit_llvm);311Args.ClaimAllArgs(options::OPT_w); // Other warning options are already312// handled somewhere else.313Args.ClaimAllArgs(options::OPT_static_libgcc);314315//----------------------------------------------------------------------------316//317//----------------------------------------------------------------------------318if (Args.hasArg(options::OPT_s))319CmdArgs.push_back("-s");320321if (Args.hasArg(options::OPT_r))322CmdArgs.push_back("-r");323324for (const auto &Opt : HTC.ExtraOpts)325CmdArgs.push_back(Opt.c_str());326327if (!UseLLD) {328CmdArgs.push_back("-march=hexagon");329CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));330}331332if (IsShared) {333CmdArgs.push_back("-shared");334// The following should be the default, but doing as hexagon-gcc does.335CmdArgs.push_back("-call_shared");336}337338if (IsStatic)339CmdArgs.push_back("-static");340341if (IsPIE && !IsShared)342CmdArgs.push_back("-pie");343344if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {345CmdArgs.push_back(Args.MakeArgString("-G" + Twine(*G)));346UseG0 = *G == 0;347}348349CmdArgs.push_back("-o");350CmdArgs.push_back(Output.getFilename());351352if (HTC.getTriple().isMusl()) {353if (!Args.hasArg(options::OPT_shared, options::OPT_static))354CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");355356if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,357options::OPT_nostdlib))358CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));359else if (Args.hasArg(options::OPT_shared) &&360!Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))361CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));362363CmdArgs.push_back(364Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));365Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,366options::OPT_t, options::OPT_u_Group});367AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);368369ToolChain::UnwindLibType UNW = HTC.GetUnwindLibType(Args);370371if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {372if (NeedsSanitizerDeps) {373linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);374375if (UNW != ToolChain::UNW_None)376CmdArgs.push_back("-lunwind");377}378if (NeedsXRayDeps)379linkXRayRuntimeDeps(HTC, Args, CmdArgs);380381if (!Args.hasArg(options::OPT_nolibc))382CmdArgs.push_back("-lc");383CmdArgs.push_back("-lclang_rt.builtins-hexagon");384}385if (D.CCCIsCXX()) {386if (HTC.ShouldLinkCXXStdlib(Args))387HTC.AddCXXStdlibLibArgs(Args, CmdArgs);388}389const ToolChain::path_list &LibPaths = HTC.getFilePaths();390for (const auto &LibPath : LibPaths)391CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));392Args.ClaimAllArgs(options::OPT_L);393return;394}395396//----------------------------------------------------------------------------397// moslib398//----------------------------------------------------------------------------399std::vector<std::string> OsLibs;400bool HasStandalone = false;401for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {402A->claim();403OsLibs.emplace_back(A->getValue());404HasStandalone = HasStandalone || (OsLibs.back() == "standalone");405}406if (OsLibs.empty()) {407OsLibs.push_back("standalone");408HasStandalone = true;409}410411//----------------------------------------------------------------------------412// Start Files413//----------------------------------------------------------------------------414const std::string MCpuSuffix = "/" + CpuVer.str();415const std::string MCpuG0Suffix = MCpuSuffix + "/G0";416const std::string RootDir =417HTC.getHexagonTargetDir(D.Dir, D.PrefixDirs) + "/";418const std::string StartSubDir =419"hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);420421auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,422const char *Name) -> std::string {423std::string RelName = SubDir + Name;424std::string P = HTC.GetFilePath(RelName.c_str());425if (llvm::sys::fs::exists(P))426return P;427return RootDir + RelName;428};429430if (IncStdLib && IncStartFiles) {431if (!IsShared) {432if (HasStandalone) {433std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");434CmdArgs.push_back(Args.MakeArgString(Crt0SA));435}436std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");437CmdArgs.push_back(Args.MakeArgString(Crt0));438}439std::string Init = UseShared440? Find(RootDir, StartSubDir + "/pic", "/initS.o")441: Find(RootDir, StartSubDir, "/init.o");442CmdArgs.push_back(Args.MakeArgString(Init));443}444445//----------------------------------------------------------------------------446// Library Search Paths447//----------------------------------------------------------------------------448const ToolChain::path_list &LibPaths = HTC.getFilePaths();449for (const auto &LibPath : LibPaths)450CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));451Args.ClaimAllArgs(options::OPT_L);452453//----------------------------------------------------------------------------454//455//----------------------------------------------------------------------------456Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,457options::OPT_t, options::OPT_u_Group});458459AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);460461//----------------------------------------------------------------------------462// Libraries463//----------------------------------------------------------------------------464if (IncStdLib && IncDefLibs) {465if (D.CCCIsCXX()) {466if (HTC.ShouldLinkCXXStdlib(Args))467HTC.AddCXXStdlibLibArgs(Args, CmdArgs);468CmdArgs.push_back("-lm");469}470471CmdArgs.push_back("--start-group");472473if (!IsShared) {474for (StringRef Lib : OsLibs)475CmdArgs.push_back(Args.MakeArgString("-l" + Lib));476if (!Args.hasArg(options::OPT_nolibc))477CmdArgs.push_back("-lc");478}479CmdArgs.push_back("-lgcc");480481CmdArgs.push_back("--end-group");482}483484//----------------------------------------------------------------------------485// End files486//----------------------------------------------------------------------------487if (IncStdLib && IncStartFiles) {488std::string Fini = UseShared489? Find(RootDir, StartSubDir + "/pic", "/finiS.o")490: Find(RootDir, StartSubDir, "/fini.o");491CmdArgs.push_back(Args.MakeArgString(Fini));492}493}494495void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,496const InputInfo &Output,497const InputInfoList &Inputs,498const ArgList &Args,499const char *LinkingOutput) const {500auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());501502ArgStringList CmdArgs;503constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,504LinkingOutput);505506const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());507C.addCommand(std::make_unique<Command>(JA, *this,508ResponseFileSupport::AtFileCurCP(),509Exec, CmdArgs, Inputs, Output));510}511// Hexagon tools end.512513/// Hexagon Toolchain514515std::string HexagonToolChain::getHexagonTargetDir(516const std::string &InstalledDir,517const SmallVectorImpl<std::string> &PrefixDirs) const {518std::string InstallRelDir;519const Driver &D = getDriver();520521// Locate the rest of the toolchain ...522for (auto &I : PrefixDirs)523if (D.getVFS().exists(I))524return I;525526if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))527return InstallRelDir;528529return InstalledDir;530}531532std::optional<unsigned>533HexagonToolChain::getSmallDataThreshold(const ArgList &Args) {534StringRef Gn = "";535if (Arg *A = Args.getLastArg(options::OPT_G)) {536Gn = A->getValue();537} else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,538options::OPT_fPIC)) {539Gn = "0";540}541542unsigned G;543if (!Gn.getAsInteger(10, G))544return G;545546return std::nullopt;547}548549std::string HexagonToolChain::getCompilerRTPath() const {550SmallString<128> Dir(getDriver().SysRoot);551llvm::sys::path::append(Dir, "usr", "lib");552if (!SelectedMultilibs.empty()) {553Dir += SelectedMultilibs.back().gccSuffix();554}555return std::string(Dir);556}557558void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,559ToolChain::path_list &LibPaths) const {560const Driver &D = getDriver();561562//----------------------------------------------------------------------------563// -L Args564//----------------------------------------------------------------------------565for (Arg *A : Args.filtered(options::OPT_L))566llvm::append_range(LibPaths, A->getValues());567568//----------------------------------------------------------------------------569// Other standard paths570//----------------------------------------------------------------------------571std::vector<std::string> RootDirs;572std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),573std::back_inserter(RootDirs));574575std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);576if (!llvm::is_contained(RootDirs, TargetDir))577RootDirs.push_back(TargetDir);578579bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);580// Assume G0 with -shared.581bool HasG0 = Args.hasArg(options::OPT_shared);582if (auto G = getSmallDataThreshold(Args))583HasG0 = *G == 0;584585const std::string CpuVer = GetTargetCPUVersion(Args).str();586for (auto &Dir : RootDirs) {587std::string LibDir = Dir + "/hexagon/lib";588std::string LibDirCpu = LibDir + '/' + CpuVer;589if (HasG0) {590if (HasPIC)591LibPaths.push_back(LibDirCpu + "/G0/pic");592LibPaths.push_back(LibDirCpu + "/G0");593}594LibPaths.push_back(LibDirCpu);595LibPaths.push_back(LibDir);596}597}598599HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,600const llvm::opt::ArgList &Args)601: Linux(D, Triple, Args) {602const std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);603604// Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to605// program paths606const std::string BinDir(TargetDir + "/bin");607if (D.getVFS().exists(BinDir))608getProgramPaths().push_back(BinDir);609610ToolChain::path_list &LibPaths = getFilePaths();611612// Remove paths added by Linux toolchain. Currently Hexagon_TC really targets613// 'elf' OS type, so the Linux paths are not appropriate. When we actually614// support 'linux' we'll need to fix this up615LibPaths.clear();616getHexagonLibraryPaths(Args, LibPaths);617}618619HexagonToolChain::~HexagonToolChain() {}620621void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,622ArgStringList &CmdArgs) const {623CXXStdlibType Type = GetCXXStdlibType(Args);624ToolChain::UnwindLibType UNW = GetUnwindLibType(Args);625if (UNW != ToolChain::UNW_None && UNW != ToolChain::UNW_CompilerRT) {626const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);627if (A) {628getDriver().Diag(diag::err_drv_unsupported_unwind_for_platform)629<< A->getValue() << getTriple().normalize();630return;631}632}633634switch (Type) {635case ToolChain::CST_Libcxx:636CmdArgs.push_back("-lc++");637if (Args.hasArg(options::OPT_fexperimental_library))638CmdArgs.push_back("-lc++experimental");639CmdArgs.push_back("-lc++abi");640if (UNW != ToolChain::UNW_None)641CmdArgs.push_back("-lunwind");642break;643644case ToolChain::CST_Libstdcxx:645CmdArgs.push_back("-lstdc++");646break;647}648}649650Tool *HexagonToolChain::buildAssembler() const {651return new tools::hexagon::Assembler(*this);652}653654Tool *HexagonToolChain::buildLinker() const {655return new tools::hexagon::Linker(*this);656}657658unsigned HexagonToolChain::getOptimizationLevel(659const llvm::opt::ArgList &DriverArgs) const {660// Copied in large part from lib/Frontend/CompilerInvocation.cpp.661Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);662if (!A)663return 0;664665if (A->getOption().matches(options::OPT_O0))666return 0;667if (A->getOption().matches(options::OPT_Ofast) ||668A->getOption().matches(options::OPT_O4))669return 3;670assert(A->getNumValues() != 0);671StringRef S(A->getValue());672if (S == "s" || S == "z" || S.empty())673return 2;674if (S == "g")675return 1;676677unsigned OptLevel;678if (S.getAsInteger(10, OptLevel))679return 0;680return OptLevel;681}682683void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,684ArgStringList &CC1Args,685Action::OffloadKind) const {686687bool UseInitArrayDefault = getTriple().isMusl();688689if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,690options::OPT_fno_use_init_array,691UseInitArrayDefault))692CC1Args.push_back("-fno-use-init-array");693694if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {695CC1Args.push_back("-target-feature");696CC1Args.push_back("+reserved-r19");697}698if (isAutoHVXEnabled(DriverArgs)) {699CC1Args.push_back("-mllvm");700CC1Args.push_back("-hexagon-autohvx");701}702}703704void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,705ArgStringList &CC1Args) const {706if (DriverArgs.hasArg(options::OPT_nostdinc))707return;708709const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();710const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();711712const Driver &D = getDriver();713SmallString<128> ResourceDirInclude(D.ResourceDir);714if (!IsELF) {715llvm::sys::path::append(ResourceDirInclude, "include");716if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&717(!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))718addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);719}720if (DriverArgs.hasArg(options::OPT_nostdlibinc))721return;722723const bool HasSysRoot = !D.SysRoot.empty();724if (HasSysRoot) {725SmallString<128> P(D.SysRoot);726if (IsLinuxMusl)727llvm::sys::path::append(P, "usr/include");728else729llvm::sys::path::append(P, "include");730731addExternCSystemInclude(DriverArgs, CC1Args, P.str());732// LOCAL_INCLUDE_DIR733addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");734// TOOL_INCLUDE_DIR735AddMultilibIncludeArgs(DriverArgs, CC1Args);736}737738if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)739addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);740741if (HasSysRoot)742return;743std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);744addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");745}746747void HexagonToolChain::addLibCxxIncludePaths(748const llvm::opt::ArgList &DriverArgs,749llvm::opt::ArgStringList &CC1Args) const {750const Driver &D = getDriver();751if (!D.SysRoot.empty() && getTriple().isMusl())752addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",753DriverArgs, CC1Args);754else if (getTriple().isMusl())755addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,756CC1Args);757else {758std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);759addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",760DriverArgs, CC1Args);761}762}763void HexagonToolChain::addLibStdCxxIncludePaths(764const llvm::opt::ArgList &DriverArgs,765llvm::opt::ArgStringList &CC1Args) const {766const Driver &D = getDriver();767std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);768addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",769DriverArgs, CC1Args);770}771772ToolChain::CXXStdlibType773HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {774Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);775if (!A) {776if (getTriple().isMusl())777return ToolChain::CST_Libcxx;778else779return ToolChain::CST_Libstdcxx;780}781StringRef Value = A->getValue();782if (Value != "libstdc++" && Value != "libc++")783getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);784785if (Value == "libstdc++")786return ToolChain::CST_Libstdcxx;787else if (Value == "libc++")788return ToolChain::CST_Libcxx;789else790return ToolChain::CST_Libstdcxx;791}792793bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {794if (Arg *A = Args.getLastArg(options::OPT_fvectorize,795options::OPT_fno_vectorize))796return A->getOption().matches(options::OPT_fvectorize);797return false;798}799800//801// Returns the default CPU for Hexagon. This is the default compilation target802// if no Hexagon processor is selected at the command-line.803//804StringRef HexagonToolChain::GetDefaultCPU() {805return "hexagonv60";806}807808StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {809Arg *CpuArg = nullptr;810if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))811CpuArg = A;812813StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();814CPU.consume_front("hexagon");815return CPU;816}817818819