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