815 lines · cpp
1//===--- Hexagon.cpp - Hexagon ToolChain Implementations --------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Hexagon.h"10#include "clang/Driver/CommonArgs.h"11#include "clang/Driver/Compilation.h"12#include "clang/Driver/Driver.h"13#include "clang/Driver/InputInfo.h"14#include "clang/Options/Options.h"15#include "llvm/Option/ArgList.h"16#include "llvm/Support/FileSystem.h"17#include "llvm/Support/Path.h"18#include "llvm/Support/VirtualFileSystem.h"19 20using namespace clang::driver;21using namespace clang::driver::tools;22using namespace clang::driver::toolchains;23using namespace clang;24using namespace llvm::opt;25 26// Default hvx-length for various versions.27static StringRef getDefaultHvxLength(StringRef HvxVer) {28 return llvm::StringSwitch<StringRef>(HvxVer)29 .Case("v60", "64b")30 .Case("v62", "64b")31 .Case("v65", "64b")32 .Default("128b");33}34 35static void handleHVXWarnings(const Driver &D, const ArgList &Args) {36 // Handle the unsupported values passed to mhvx-length.37 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {38 StringRef Val = A->getValue();39 if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))40 D.Diag(diag::err_drv_unsupported_option_argument)41 << A->getSpelling() << Val;42 }43}44 45// Handle hvx target features explicitly.46static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,47 std::vector<StringRef> &Features,48 StringRef Cpu, bool &HasHVX) {49 // Handle HVX warnings.50 handleHVXWarnings(D, Args);51 52 auto makeFeature = [&Args](Twine T, bool Enable) -> StringRef {53 const std::string &S = T.str();54 StringRef Opt(S);55 Opt.consume_back("=");56 if (Opt.starts_with("mno-"))57 Opt = Opt.drop_front(4);58 else if (Opt.starts_with("m"))59 Opt = Opt.drop_front(1);60 return Args.MakeArgString(Twine(Enable ? "+" : "-") + Twine(Opt));61 };62 63 auto withMinus = [](StringRef S) -> std::string {64 return "-" + S.str();65 };66 67 // Drop tiny core suffix for HVX version.68 std::string HvxVer =69 (Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();70 HasHVX = false;71 72 // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags73 // are both present, the last one wins.74 Arg *HvxEnablingArg =75 Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,76 options::OPT_mno_hexagon_hvx);77 if (HvxEnablingArg) {78 if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))79 HvxEnablingArg = nullptr;80 }81 82 if (HvxEnablingArg) {83 // If -mhvx[=] was given, it takes precedence.84 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,85 options::OPT_mhexagon_hvx_EQ)) {86 // If the version was given, set HvxVer. Otherwise HvxVer87 // will remain equal to the CPU version.88 if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))89 HvxVer = StringRef(A->getValue()).lower();90 }91 HasHVX = true;92 Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));93 } else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {94 // If there was an explicit -mno-hvx, add -hvx to target features.95 Features.push_back(makeFeature(A->getOption().getName(), false));96 }97 98 StringRef HvxLen = getDefaultHvxLength(HvxVer);99 100 // Handle -mhvx-length=.101 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {102 // These flags are valid only if HVX in enabled.103 if (!HasHVX)104 D.Diag(diag::err_drv_needs_hvx) << withMinus(A->getOption().getName());105 else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))106 HvxLen = A->getValue();107 }108 109 if (HasHVX) {110 StringRef L = makeFeature(Twine("hvx-length") + HvxLen.lower(), true);111 Features.push_back(L);112 }113 114 unsigned HvxVerNum;115 // getAsInteger returns 'true' on error.116 if (StringRef(HvxVer).drop_front(1).getAsInteger(10, HvxVerNum))117 HvxVerNum = 0;118 119 // Handle HVX floating point flags.120 auto checkFlagHvxVersion =121 [&](auto FlagOn, auto FlagOff,122 unsigned MinVerNum) -> std::optional<StringRef> {123 // Return an std::optional<StringRef>:124 // - std::nullopt indicates a verification failure, or that the flag was not125 // present in Args.126 // - Otherwise the returned value is that name of the feature to add127 // to Features.128 Arg *A = Args.getLastArg(FlagOn, FlagOff);129 if (!A)130 return std::nullopt;131 132 StringRef OptName = A->getOption().getName();133 if (A->getOption().matches(FlagOff))134 return makeFeature(OptName, false);135 136 if (!HasHVX) {137 D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);138 return std::nullopt;139 }140 if (HvxVerNum < MinVerNum) {141 D.Diag(diag::err_drv_needs_hvx_version)142 << withMinus(OptName) << ("v" + std::to_string(HvxVerNum));143 return std::nullopt;144 }145 return makeFeature(OptName, true);146 };147 148 if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,149 options::OPT_mno_hexagon_hvx_qfloat, 68)) {150 Features.push_back(*F);151 }152 if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,153 options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {154 Features.push_back(*F);155 }156}157 158// Hexagon target features.159void hexagon::getHexagonTargetFeatures(const Driver &D,160 const llvm::Triple &Triple,161 const ArgList &Args,162 std::vector<StringRef> &Features) {163 handleTargetFeaturesGroup(D, Triple, Args, Features,164 options::OPT_m_hexagon_Features_Group);165 166 bool UseLongCalls = false;167 if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,168 options::OPT_mno_long_calls)) {169 if (A->getOption().matches(options::OPT_mlong_calls))170 UseLongCalls = true;171 }172 173 Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");174 175 bool HasHVX = false;176 StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));177 // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors178 // have no dependency on micro-architecture.179 const bool TinyCore = Cpu.contains('t');180 181 if (TinyCore)182 Cpu = Cpu.take_front(Cpu.size() - 1);183 184 handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);185 186 if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)187 D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";188}189 190// Hexagon tools start.191void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,192 ArgStringList &CmdArgs) const {193}194 195void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,196 const InputInfo &Output,197 const InputInfoList &Inputs,198 const ArgList &Args,199 const char *LinkingOutput) const {200 claimNoWarnArgs(Args);201 202 auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());203 const Driver &D = HTC.getDriver();204 ArgStringList CmdArgs;205 206 CmdArgs.push_back("--arch=hexagon");207 208 RenderExtraToolArgs(JA, CmdArgs);209 210 const char *AsName = "llvm-mc";211 CmdArgs.push_back("-filetype=obj");212 CmdArgs.push_back(Args.MakeArgString(213 "-mcpu=hexagon" +214 toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));215 216 addSanitizerRuntimes(HTC, Args, CmdArgs);217 218 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");219 if (Output.isFilename()) {220 CmdArgs.push_back("-o");221 CmdArgs.push_back(Output.getFilename());222 } else {223 CmdArgs.push_back("-fsyntax-only");224 }225 226 if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,227 options::OPT_mno_hexagon_hvx_ieee_fp)) {228 if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))229 CmdArgs.push_back("-mhvx-ieee-fp");230 }231 232 if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {233 CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(*G)));234 }235 236 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);237 238 // Only pass -x if gcc will understand it; otherwise hope gcc239 // understands the suffix correctly. The main use case this would go240 // wrong in is for linker inputs if they happened to have an odd241 // suffix; really the only way to get this to happen is a command242 // like '-x foobar a.c' which will treat a.c like a linker input.243 //244 // FIXME: For the linker case specifically, can we safely convert245 // inputs into '-Wl,' options?246 for (const auto &II : Inputs) {247 // Don't try to pass LLVM or AST inputs to a generic gcc.248 if (types::isLLVMIR(II.getType()))249 D.Diag(clang::diag::err_drv_no_linker_llvm_support)250 << HTC.getTripleString();251 else if (II.getType() == types::TY_AST)252 D.Diag(clang::diag::err_drv_no_ast_support)253 << HTC.getTripleString();254 else if (II.getType() == types::TY_ModuleFile)255 D.Diag(diag::err_drv_no_module_support)256 << HTC.getTripleString();257 258 if (II.isFilename())259 CmdArgs.push_back(II.getFilename());260 else261 // Don't render as input, we need gcc to do the translations.262 // FIXME: What is this?263 II.getInputArg().render(Args, CmdArgs);264 }265 266 auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));267 C.addCommand(std::make_unique<Command>(JA, *this,268 ResponseFileSupport::AtFileCurCP(),269 Exec, CmdArgs, Inputs, Output));270}271 272void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,273 ArgStringList &CmdArgs) const {274}275 276static void277constructHexagonLinkArgs(Compilation &C, const JobAction &JA,278 const toolchains::HexagonToolChain &HTC,279 const InputInfo &Output, const InputInfoList &Inputs,280 const ArgList &Args, ArgStringList &CmdArgs,281 const char *LinkingOutput) {282 283 const Driver &D = HTC.getDriver();284 285 //----------------------------------------------------------------------------286 //287 //----------------------------------------------------------------------------288 bool IsStatic = Args.hasArg(options::OPT_static);289 bool IsShared = Args.hasArg(options::OPT_shared);290 bool IsPIE = Args.hasArg(options::OPT_pie);291 bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);292 bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);293 bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);294 bool UseG0 = false;295 bool UseLLD = false;296 const char *Exec = Args.MakeArgString(HTC.GetLinkerPath(&UseLLD));297 UseLLD = UseLLD || llvm::sys::path::filename(Exec).ends_with("ld.lld") ||298 llvm::sys::path::stem(Exec).ends_with("ld.lld");299 bool UseShared = IsShared && !IsStatic;300 StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);301 302 bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);303 bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);304 305 //----------------------------------------------------------------------------306 // Silence warnings for various options307 //----------------------------------------------------------------------------308 Args.ClaimAllArgs(options::OPT_g_Group);309 Args.ClaimAllArgs(options::OPT_emit_llvm);310 Args.ClaimAllArgs(options::OPT_w); // Other warning options are already311 // handled somewhere else.312 Args.ClaimAllArgs(options::OPT_static_libgcc);313 314 CmdArgs.push_back("--eh-frame-hdr");315 //----------------------------------------------------------------------------316 //317 //----------------------------------------------------------------------------318 if (Args.hasArg(options::OPT_s))319 CmdArgs.push_back("-s");320 321 if (Args.hasArg(options::OPT_r))322 CmdArgs.push_back("-r");323 324 for (const auto &Opt : HTC.ExtraOpts)325 CmdArgs.push_back(Opt.c_str());326 327 if (!UseLLD) {328 CmdArgs.push_back("-march=hexagon");329 CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));330 }331 332 if (IsShared) {333 CmdArgs.push_back("-shared");334 // The following should be the default, but doing as hexagon-gcc does.335 CmdArgs.push_back("-call_shared");336 }337 338 if (IsStatic)339 CmdArgs.push_back("-static");340 341 if (IsPIE && !IsShared)342 CmdArgs.push_back("-pie");343 344 if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {345 CmdArgs.push_back(Args.MakeArgString("-G" + Twine(*G)));346 UseG0 = *G == 0;347 }348 349 CmdArgs.push_back("-o");350 CmdArgs.push_back(Output.getFilename());351 352 if (HTC.getTriple().isMusl()) {353 if (!Args.hasArg(options::OPT_shared, options::OPT_static))354 CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");355 356 if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,357 options::OPT_nostdlib))358 CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));359 else if (Args.hasArg(options::OPT_shared) &&360 !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))361 CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));362 363 CmdArgs.push_back(364 Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));365 Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,366 options::OPT_t, options::OPT_u_Group});367 AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);368 369 ToolChain::UnwindLibType UNW = HTC.GetUnwindLibType(Args);370 371 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {372 if (NeedsSanitizerDeps) {373 linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);374 375 if (UNW != ToolChain::UNW_None)376 CmdArgs.push_back("-lunwind");377 }378 if (NeedsXRayDeps)379 linkXRayRuntimeDeps(HTC, Args, CmdArgs);380 381 if (!Args.hasArg(options::OPT_nolibc))382 CmdArgs.push_back("-lc");383 CmdArgs.push_back("-lclang_rt.builtins-hexagon");384 }385 if (D.CCCIsCXX()) {386 if (HTC.ShouldLinkCXXStdlib(Args))387 HTC.AddCXXStdlibLibArgs(Args, CmdArgs);388 }389 const ToolChain::path_list &LibPaths = HTC.getFilePaths();390 for (const auto &LibPath : LibPaths)391 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));392 Args.ClaimAllArgs(options::OPT_L);393 return;394 }395 396 //----------------------------------------------------------------------------397 // moslib398 //----------------------------------------------------------------------------399 std::vector<std::string> OsLibs;400 bool HasStandalone = false;401 for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {402 A->claim();403 OsLibs.emplace_back(A->getValue());404 HasStandalone = HasStandalone || (OsLibs.back() == "standalone");405 }406 if (OsLibs.empty()) {407 OsLibs.push_back("standalone");408 HasStandalone = true;409 }410 411 //----------------------------------------------------------------------------412 // Start Files413 //----------------------------------------------------------------------------414 const std::string MCpuSuffix = "/" + CpuVer.str();415 const std::string MCpuG0Suffix = MCpuSuffix + "/G0";416 const std::string RootDir =417 HTC.getHexagonTargetDir(D.Dir, D.PrefixDirs) + "/";418 const std::string StartSubDir =419 "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);420 421 auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,422 const char *Name) -> std::string {423 std::string RelName = SubDir + Name;424 std::string P = HTC.GetFilePath(RelName.c_str());425 if (llvm::sys::fs::exists(P))426 return P;427 return RootDir + RelName;428 };429 430 if (IncStdLib && IncStartFiles) {431 if (!IsShared) {432 if (HasStandalone) {433 std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");434 CmdArgs.push_back(Args.MakeArgString(Crt0SA));435 }436 std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");437 CmdArgs.push_back(Args.MakeArgString(Crt0));438 }439 std::string Init = UseShared440 ? Find(RootDir, StartSubDir + "/pic", "/initS.o")441 : Find(RootDir, StartSubDir, "/init.o");442 CmdArgs.push_back(Args.MakeArgString(Init));443 }444 445 //----------------------------------------------------------------------------446 // Library Search Paths447 //----------------------------------------------------------------------------448 const ToolChain::path_list &LibPaths = HTC.getFilePaths();449 for (const auto &LibPath : LibPaths)450 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));451 Args.ClaimAllArgs(options::OPT_L);452 453 //----------------------------------------------------------------------------454 //455 //----------------------------------------------------------------------------456 Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,457 options::OPT_t, options::OPT_u_Group});458 459 AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);460 461 //----------------------------------------------------------------------------462 // Libraries463 //----------------------------------------------------------------------------464 if (IncStdLib && IncDefLibs) {465 if (D.CCCIsCXX()) {466 if (HTC.ShouldLinkCXXStdlib(Args))467 HTC.AddCXXStdlibLibArgs(Args, CmdArgs);468 CmdArgs.push_back("-lm");469 }470 471 CmdArgs.push_back("--start-group");472 473 if (!IsShared) {474 for (StringRef Lib : OsLibs)475 CmdArgs.push_back(Args.MakeArgString("-l" + Lib));476 if (!Args.hasArg(options::OPT_nolibc))477 CmdArgs.push_back("-lc");478 }479 CmdArgs.push_back("-lgcc");480 481 CmdArgs.push_back("--end-group");482 }483 484 //----------------------------------------------------------------------------485 // End files486 //----------------------------------------------------------------------------487 if (IncStdLib && IncStartFiles) {488 std::string Fini = UseShared489 ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")490 : Find(RootDir, StartSubDir, "/fini.o");491 CmdArgs.push_back(Args.MakeArgString(Fini));492 }493}494 495void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,496 const InputInfo &Output,497 const InputInfoList &Inputs,498 const ArgList &Args,499 const char *LinkingOutput) const {500 auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());501 502 ArgStringList CmdArgs;503 constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,504 LinkingOutput);505 506 const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());507 C.addCommand(std::make_unique<Command>(JA, *this,508 ResponseFileSupport::AtFileCurCP(),509 Exec, CmdArgs, Inputs, Output));510}511// Hexagon tools end.512 513/// Hexagon Toolchain514 515std::string HexagonToolChain::getHexagonTargetDir(516 const std::string &InstalledDir,517 const SmallVectorImpl<std::string> &PrefixDirs) const {518 std::string InstallRelDir;519 const Driver &D = getDriver();520 521 // Locate the rest of the toolchain ...522 for (auto &I : PrefixDirs)523 if (D.getVFS().exists(I))524 return I;525 526 if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))527 return InstallRelDir;528 529 return InstalledDir;530}531 532std::optional<unsigned>533HexagonToolChain::getSmallDataThreshold(const ArgList &Args) {534 StringRef Gn = "";535 if (Arg *A = Args.getLastArg(options::OPT_G)) {536 Gn = A->getValue();537 } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,538 options::OPT_fPIC)) {539 Gn = "0";540 }541 542 unsigned G;543 if (!Gn.getAsInteger(10, G))544 return G;545 546 return std::nullopt;547}548 549std::string HexagonToolChain::getCompilerRTPath() const {550 SmallString<128> Dir(getDriver().SysRoot);551 llvm::sys::path::append(Dir, "usr", "lib");552 if (!SelectedMultilibs.empty()) {553 Dir += SelectedMultilibs.back().gccSuffix();554 }555 return std::string(Dir);556}557 558void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,559 ToolChain::path_list &LibPaths) const {560 const Driver &D = getDriver();561 562 //----------------------------------------------------------------------------563 // -L Args564 //----------------------------------------------------------------------------565 for (Arg *A : Args.filtered(options::OPT_L))566 llvm::append_range(LibPaths, A->getValues());567 568 //----------------------------------------------------------------------------569 // Other standard paths570 //----------------------------------------------------------------------------571 std::vector<std::string> RootDirs;572 std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),573 std::back_inserter(RootDirs));574 575 std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);576 if (!llvm::is_contained(RootDirs, TargetDir))577 RootDirs.push_back(TargetDir);578 579 bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);580 // Assume G0 with -shared.581 bool HasG0 = Args.hasArg(options::OPT_shared);582 if (auto G = getSmallDataThreshold(Args))583 HasG0 = *G == 0;584 585 const std::string CpuVer = GetTargetCPUVersion(Args).str();586 for (auto &Dir : RootDirs) {587 std::string LibDir = Dir + "/hexagon/lib";588 std::string LibDirCpu = LibDir + '/' + CpuVer;589 if (HasG0) {590 if (HasPIC)591 LibPaths.push_back(LibDirCpu + "/G0/pic");592 LibPaths.push_back(LibDirCpu + "/G0");593 }594 LibPaths.push_back(LibDirCpu);595 LibPaths.push_back(LibDir);596 }597}598 599HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,600 const llvm::opt::ArgList &Args)601 : Linux(D, Triple, Args) {602 const std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);603 604 // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to605 // program paths606 const std::string BinDir(TargetDir + "/bin");607 if (D.getVFS().exists(BinDir))608 getProgramPaths().push_back(BinDir);609 610 ToolChain::path_list &LibPaths = getFilePaths();611 612 // 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 up615 LibPaths.clear();616 getHexagonLibraryPaths(Args, LibPaths);617}618 619HexagonToolChain::~HexagonToolChain() {}620 621void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,622 ArgStringList &CmdArgs) const {623 CXXStdlibType Type = GetCXXStdlibType(Args);624 ToolChain::UnwindLibType UNW = GetUnwindLibType(Args);625 if (UNW != ToolChain::UNW_None && UNW != ToolChain::UNW_CompilerRT) {626 const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);627 if (A) {628 getDriver().Diag(diag::err_drv_unsupported_unwind_for_platform)629 << A->getValue() << getTriple().normalize();630 return;631 }632 }633 634 switch (Type) {635 case ToolChain::CST_Libcxx:636 CmdArgs.push_back("-lc++");637 if (Args.hasArg(options::OPT_fexperimental_library))638 CmdArgs.push_back("-lc++experimental");639 CmdArgs.push_back("-lc++abi");640 if (UNW != ToolChain::UNW_None)641 CmdArgs.push_back("-lunwind");642 break;643 644 case ToolChain::CST_Libstdcxx:645 CmdArgs.push_back("-lstdc++");646 break;647 }648}649 650Tool *HexagonToolChain::buildAssembler() const {651 return new tools::hexagon::Assembler(*this);652}653 654Tool *HexagonToolChain::buildLinker() const {655 return new tools::hexagon::Linker(*this);656}657 658unsigned HexagonToolChain::getOptimizationLevel(659 const llvm::opt::ArgList &DriverArgs) const {660 // Copied in large part from lib/Frontend/CompilerInvocation.cpp.661 Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);662 if (!A)663 return 0;664 665 if (A->getOption().matches(options::OPT_O0))666 return 0;667 if (A->getOption().matches(options::OPT_Ofast) ||668 A->getOption().matches(options::OPT_O4))669 return 3;670 assert(A->getNumValues() != 0);671 StringRef S(A->getValue());672 if (S == "s" || S == "z" || S.empty())673 return 2;674 if (S == "g")675 return 1;676 677 unsigned OptLevel;678 if (S.getAsInteger(10, OptLevel))679 return 0;680 return OptLevel;681}682 683void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,684 ArgStringList &CC1Args,685 Action::OffloadKind) const {686 687 bool UseInitArrayDefault = getTriple().isMusl();688 689 if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,690 options::OPT_fno_use_init_array,691 UseInitArrayDefault))692 CC1Args.push_back("-fno-use-init-array");693 694 if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {695 CC1Args.push_back("-target-feature");696 CC1Args.push_back("+reserved-r19");697 }698 if (isAutoHVXEnabled(DriverArgs)) {699 CC1Args.push_back("-mllvm");700 CC1Args.push_back("-hexagon-autohvx");701 }702}703 704void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,705 ArgStringList &CC1Args) const {706 if (DriverArgs.hasArg(options::OPT_nostdinc))707 return;708 709 const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();710 const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();711 712 const Driver &D = getDriver();713 SmallString<128> ResourceDirInclude(D.ResourceDir);714 if (!IsELF) {715 llvm::sys::path::append(ResourceDirInclude, "include");716 if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&717 (!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))718 addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);719 }720 if (DriverArgs.hasArg(options::OPT_nostdlibinc))721 return;722 723 const bool HasSysRoot = !D.SysRoot.empty();724 if (HasSysRoot) {725 SmallString<128> P(D.SysRoot);726 if (IsLinuxMusl)727 llvm::sys::path::append(P, "usr/include");728 else729 llvm::sys::path::append(P, "include");730 731 addExternCSystemInclude(DriverArgs, CC1Args, P.str());732 // LOCAL_INCLUDE_DIR733 addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");734 // TOOL_INCLUDE_DIR735 AddMultilibIncludeArgs(DriverArgs, CC1Args);736 }737 738 if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)739 addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);740 741 if (HasSysRoot)742 return;743 std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);744 addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");745}746 747void HexagonToolChain::addLibCxxIncludePaths(748 const llvm::opt::ArgList &DriverArgs,749 llvm::opt::ArgStringList &CC1Args) const {750 const Driver &D = getDriver();751 if (!D.SysRoot.empty() && getTriple().isMusl())752 addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",753 DriverArgs, CC1Args);754 else if (getTriple().isMusl())755 addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,756 CC1Args);757 else {758 std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);759 addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",760 DriverArgs, CC1Args);761 }762}763void HexagonToolChain::addLibStdCxxIncludePaths(764 const llvm::opt::ArgList &DriverArgs,765 llvm::opt::ArgStringList &CC1Args) const {766 const Driver &D = getDriver();767 std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);768 addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",769 DriverArgs, CC1Args);770}771 772ToolChain::CXXStdlibType773HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {774 Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);775 if (!A) {776 if (getTriple().isMusl())777 return ToolChain::CST_Libcxx;778 else779 return ToolChain::CST_Libstdcxx;780 }781 StringRef Value = A->getValue();782 if (Value != "libstdc++" && Value != "libc++")783 getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);784 785 if (Value == "libstdc++")786 return ToolChain::CST_Libstdcxx;787 else if (Value == "libc++")788 return ToolChain::CST_Libcxx;789 else790 return ToolChain::CST_Libstdcxx;791}792 793bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {794 if (Arg *A = Args.getLastArg(options::OPT_fvectorize,795 options::OPT_fno_vectorize))796 return A->getOption().matches(options::OPT_fvectorize);797 return false;798}799 800//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() { return "hexagonv68"; }805 806StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {807 Arg *CpuArg = nullptr;808 if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))809 CpuArg = A;810 811 StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();812 CPU.consume_front("hexagon");813 return CPU;814}815