Hexagon.cpp 28 KB

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