Hexagon.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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->getOption().getName() << 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 = [&](auto FlagOn, auto FlagOff,
  109. unsigned MinVerNum) -> Optional<StringRef> {
  110. // Return an Optional<StringRef>:
  111. // - None indicates a verification failure, or that the flag was not
  112. // present in Args.
  113. // - Otherwise the returned value is that name of the feature to add
  114. // to Features.
  115. Arg *A = Args.getLastArg(FlagOn, FlagOff);
  116. if (!A)
  117. return None;
  118. StringRef OptName = A->getOption().getName();
  119. if (A->getOption().matches(FlagOff))
  120. return makeFeature(OptName, false);
  121. if (!HasHVX) {
  122. D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);
  123. return None;
  124. }
  125. if (HvxVerNum < MinVerNum) {
  126. D.Diag(diag::err_drv_needs_hvx_version)
  127. << withMinus(OptName) << ("v" + std::to_string(HvxVerNum));
  128. return None;
  129. }
  130. return makeFeature(OptName, true);
  131. };
  132. if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,
  133. options::OPT_mno_hexagon_hvx_qfloat, 68)) {
  134. Features.push_back(*F);
  135. }
  136. if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,
  137. options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {
  138. Features.push_back(*F);
  139. }
  140. }
  141. // Hexagon target features.
  142. void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
  143. std::vector<StringRef> &Features) {
  144. handleTargetFeaturesGroup(Args, Features,
  145. options::OPT_m_hexagon_Features_Group);
  146. bool UseLongCalls = false;
  147. if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
  148. options::OPT_mno_long_calls)) {
  149. if (A->getOption().matches(options::OPT_mlong_calls))
  150. UseLongCalls = true;
  151. }
  152. Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
  153. bool HasHVX = false;
  154. StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
  155. // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
  156. // have no dependency on micro-architecture.
  157. const bool TinyCore = Cpu.contains('t');
  158. if (TinyCore)
  159. Cpu = Cpu.take_front(Cpu.size() - 1);
  160. handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
  161. if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
  162. D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";
  163. }
  164. // Hexagon tools start.
  165. void hexagon::Assembler::RenderExtraToolArgs(const JobAction &JA,
  166. ArgStringList &CmdArgs) const {
  167. }
  168. void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
  169. const InputInfo &Output,
  170. const InputInfoList &Inputs,
  171. const ArgList &Args,
  172. const char *LinkingOutput) const {
  173. claimNoWarnArgs(Args);
  174. auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
  175. const Driver &D = HTC.getDriver();
  176. ArgStringList CmdArgs;
  177. CmdArgs.push_back("--arch=hexagon");
  178. RenderExtraToolArgs(JA, CmdArgs);
  179. const char *AsName = "llvm-mc";
  180. CmdArgs.push_back("-filetype=obj");
  181. CmdArgs.push_back(Args.MakeArgString(
  182. "-mcpu=hexagon" +
  183. toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
  184. addSanitizerRuntimes(HTC, Args, CmdArgs);
  185. if (Output.isFilename()) {
  186. CmdArgs.push_back("-o");
  187. CmdArgs.push_back(Output.getFilename());
  188. } else {
  189. assert(Output.isNothing() && "Unexpected output");
  190. CmdArgs.push_back("-fsyntax-only");
  191. }
  192. if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,
  193. options::OPT_mno_hexagon_hvx_ieee_fp)) {
  194. if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))
  195. CmdArgs.push_back("-mhvx-ieee-fp");
  196. }
  197. if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
  198. CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
  199. }
  200. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  201. // Only pass -x if gcc will understand it; otherwise hope gcc
  202. // understands the suffix correctly. The main use case this would go
  203. // wrong in is for linker inputs if they happened to have an odd
  204. // suffix; really the only way to get this to happen is a command
  205. // like '-x foobar a.c' which will treat a.c like a linker input.
  206. //
  207. // FIXME: For the linker case specifically, can we safely convert
  208. // inputs into '-Wl,' options?
  209. for (const auto &II : Inputs) {
  210. // Don't try to pass LLVM or AST inputs to a generic gcc.
  211. if (types::isLLVMIR(II.getType()))
  212. D.Diag(clang::diag::err_drv_no_linker_llvm_support)
  213. << HTC.getTripleString();
  214. else if (II.getType() == types::TY_AST)
  215. D.Diag(clang::diag::err_drv_no_ast_support)
  216. << HTC.getTripleString();
  217. else if (II.getType() == types::TY_ModuleFile)
  218. D.Diag(diag::err_drv_no_module_support)
  219. << HTC.getTripleString();
  220. if (II.isFilename())
  221. CmdArgs.push_back(II.getFilename());
  222. else
  223. // Don't render as input, we need gcc to do the translations.
  224. // FIXME: What is this?
  225. II.getInputArg().render(Args, CmdArgs);
  226. }
  227. auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
  228. C.addCommand(std::make_unique<Command>(JA, *this,
  229. ResponseFileSupport::AtFileCurCP(),
  230. Exec, CmdArgs, Inputs, Output));
  231. }
  232. void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
  233. ArgStringList &CmdArgs) const {
  234. }
  235. static void
  236. constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
  237. const toolchains::HexagonToolChain &HTC,
  238. const InputInfo &Output, const InputInfoList &Inputs,
  239. const ArgList &Args, ArgStringList &CmdArgs,
  240. const char *LinkingOutput) {
  241. const Driver &D = HTC.getDriver();
  242. //----------------------------------------------------------------------------
  243. //
  244. //----------------------------------------------------------------------------
  245. bool IsStatic = Args.hasArg(options::OPT_static);
  246. bool IsShared = Args.hasArg(options::OPT_shared);
  247. bool IsPIE = Args.hasArg(options::OPT_pie);
  248. bool IncStdLib = !Args.hasArg(options::OPT_nostdlib);
  249. bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
  250. bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
  251. bool UseG0 = false;
  252. const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
  253. bool UseLLD = (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") ||
  254. llvm::sys::path::stem(Exec).equals_insensitive("ld.lld"));
  255. bool UseShared = IsShared && !IsStatic;
  256. StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
  257. bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
  258. bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
  259. //----------------------------------------------------------------------------
  260. // Silence warnings for various options
  261. //----------------------------------------------------------------------------
  262. Args.ClaimAllArgs(options::OPT_g_Group);
  263. Args.ClaimAllArgs(options::OPT_emit_llvm);
  264. Args.ClaimAllArgs(options::OPT_w); // Other warning options are already
  265. // handled somewhere else.
  266. Args.ClaimAllArgs(options::OPT_static_libgcc);
  267. //----------------------------------------------------------------------------
  268. //
  269. //----------------------------------------------------------------------------
  270. if (Args.hasArg(options::OPT_s))
  271. CmdArgs.push_back("-s");
  272. if (Args.hasArg(options::OPT_r))
  273. CmdArgs.push_back("-r");
  274. for (const auto &Opt : HTC.ExtraOpts)
  275. CmdArgs.push_back(Opt.c_str());
  276. if (!UseLLD) {
  277. CmdArgs.push_back("-march=hexagon");
  278. CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
  279. }
  280. if (IsShared) {
  281. CmdArgs.push_back("-shared");
  282. // The following should be the default, but doing as hexagon-gcc does.
  283. CmdArgs.push_back("-call_shared");
  284. }
  285. if (IsStatic)
  286. CmdArgs.push_back("-static");
  287. if (IsPIE && !IsShared)
  288. CmdArgs.push_back("-pie");
  289. if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
  290. CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
  291. UseG0 = G.getValue() == 0;
  292. }
  293. CmdArgs.push_back("-o");
  294. CmdArgs.push_back(Output.getFilename());
  295. if (HTC.getTriple().isMusl()) {
  296. if (!Args.hasArg(options::OPT_shared, options::OPT_static))
  297. CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
  298. if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
  299. options::OPT_nostdlib))
  300. CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
  301. else if (Args.hasArg(options::OPT_shared) &&
  302. !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
  303. CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
  304. CmdArgs.push_back(
  305. Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
  306. Args.AddAllArgs(CmdArgs,
  307. {options::OPT_T_Group, options::OPT_e, options::OPT_s,
  308. options::OPT_t, options::OPT_u_Group});
  309. AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
  310. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
  311. if (NeedsSanitizerDeps) {
  312. linkSanitizerRuntimeDeps(HTC, CmdArgs);
  313. CmdArgs.push_back("-lunwind");
  314. }
  315. if (NeedsXRayDeps)
  316. linkXRayRuntimeDeps(HTC, CmdArgs);
  317. CmdArgs.push_back("-lclang_rt.builtins-hexagon");
  318. CmdArgs.push_back("-lc");
  319. }
  320. if (D.CCCIsCXX()) {
  321. if (HTC.ShouldLinkCXXStdlib(Args))
  322. HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
  323. }
  324. return;
  325. }
  326. //----------------------------------------------------------------------------
  327. // moslib
  328. //----------------------------------------------------------------------------
  329. std::vector<std::string> OsLibs;
  330. bool HasStandalone = false;
  331. for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
  332. A->claim();
  333. OsLibs.emplace_back(A->getValue());
  334. HasStandalone = HasStandalone || (OsLibs.back() == "standalone");
  335. }
  336. if (OsLibs.empty()) {
  337. OsLibs.push_back("standalone");
  338. HasStandalone = true;
  339. }
  340. //----------------------------------------------------------------------------
  341. // Start Files
  342. //----------------------------------------------------------------------------
  343. const std::string MCpuSuffix = "/" + CpuVer.str();
  344. const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
  345. const std::string RootDir =
  346. HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
  347. const std::string StartSubDir =
  348. "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
  349. auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir,
  350. const char *Name) -> std::string {
  351. std::string RelName = SubDir + Name;
  352. std::string P = HTC.GetFilePath(RelName.c_str());
  353. if (llvm::sys::fs::exists(P))
  354. return P;
  355. return RootDir + RelName;
  356. };
  357. if (IncStdLib && IncStartFiles) {
  358. if (!IsShared) {
  359. if (HasStandalone) {
  360. std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o");
  361. CmdArgs.push_back(Args.MakeArgString(Crt0SA));
  362. }
  363. std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o");
  364. CmdArgs.push_back(Args.MakeArgString(Crt0));
  365. }
  366. std::string Init = UseShared
  367. ? Find(RootDir, StartSubDir + "/pic", "/initS.o")
  368. : Find(RootDir, StartSubDir, "/init.o");
  369. CmdArgs.push_back(Args.MakeArgString(Init));
  370. }
  371. //----------------------------------------------------------------------------
  372. // Library Search Paths
  373. //----------------------------------------------------------------------------
  374. const ToolChain::path_list &LibPaths = HTC.getFilePaths();
  375. for (const auto &LibPath : LibPaths)
  376. CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
  377. //----------------------------------------------------------------------------
  378. //
  379. //----------------------------------------------------------------------------
  380. Args.AddAllArgs(CmdArgs,
  381. {options::OPT_T_Group, options::OPT_e, options::OPT_s,
  382. options::OPT_t, options::OPT_u_Group});
  383. AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
  384. //----------------------------------------------------------------------------
  385. // Libraries
  386. //----------------------------------------------------------------------------
  387. if (IncStdLib && IncDefLibs) {
  388. if (D.CCCIsCXX()) {
  389. if (HTC.ShouldLinkCXXStdlib(Args))
  390. HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
  391. CmdArgs.push_back("-lm");
  392. }
  393. CmdArgs.push_back("--start-group");
  394. if (!IsShared) {
  395. for (StringRef Lib : OsLibs)
  396. CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
  397. CmdArgs.push_back("-lc");
  398. }
  399. CmdArgs.push_back("-lgcc");
  400. CmdArgs.push_back("--end-group");
  401. }
  402. //----------------------------------------------------------------------------
  403. // End files
  404. //----------------------------------------------------------------------------
  405. if (IncStdLib && IncStartFiles) {
  406. std::string Fini = UseShared
  407. ? Find(RootDir, StartSubDir + "/pic", "/finiS.o")
  408. : Find(RootDir, StartSubDir, "/fini.o");
  409. CmdArgs.push_back(Args.MakeArgString(Fini));
  410. }
  411. }
  412. void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  413. const InputInfo &Output,
  414. const InputInfoList &Inputs,
  415. const ArgList &Args,
  416. const char *LinkingOutput) const {
  417. auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain());
  418. ArgStringList CmdArgs;
  419. constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
  420. LinkingOutput);
  421. const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
  422. C.addCommand(std::make_unique<Command>(JA, *this,
  423. ResponseFileSupport::AtFileCurCP(),
  424. Exec, CmdArgs, Inputs, Output));
  425. }
  426. // Hexagon tools end.
  427. /// Hexagon Toolchain
  428. std::string HexagonToolChain::getHexagonTargetDir(
  429. const std::string &InstalledDir,
  430. const SmallVectorImpl<std::string> &PrefixDirs) const {
  431. std::string InstallRelDir;
  432. const Driver &D = getDriver();
  433. // Locate the rest of the toolchain ...
  434. for (auto &I : PrefixDirs)
  435. if (D.getVFS().exists(I))
  436. return I;
  437. if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
  438. return InstallRelDir;
  439. return InstalledDir;
  440. }
  441. Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
  442. const ArgList &Args) {
  443. StringRef Gn = "";
  444. if (Arg *A = Args.getLastArg(options::OPT_G)) {
  445. Gn = A->getValue();
  446. } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
  447. options::OPT_fPIC)) {
  448. Gn = "0";
  449. }
  450. unsigned G;
  451. if (!Gn.getAsInteger(10, G))
  452. return G;
  453. return None;
  454. }
  455. std::string HexagonToolChain::getCompilerRTPath() const {
  456. SmallString<128> Dir(getDriver().SysRoot);
  457. llvm::sys::path::append(Dir, "usr", "lib");
  458. Dir += SelectedMultilib.gccSuffix();
  459. return std::string(Dir.str());
  460. }
  461. void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
  462. ToolChain::path_list &LibPaths) const {
  463. const Driver &D = getDriver();
  464. //----------------------------------------------------------------------------
  465. // -L Args
  466. //----------------------------------------------------------------------------
  467. for (Arg *A : Args.filtered(options::OPT_L))
  468. for (const char *Value : A->getValues())
  469. LibPaths.push_back(Value);
  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.getValue() == 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. CmdArgs.push_back("-lc++abi");
  523. CmdArgs.push_back("-lunwind");
  524. break;
  525. case ToolChain::CST_Libstdcxx:
  526. CmdArgs.push_back("-lstdc++");
  527. break;
  528. }
  529. }
  530. Tool *HexagonToolChain::buildAssembler() const {
  531. return new tools::hexagon::Assembler(*this);
  532. }
  533. Tool *HexagonToolChain::buildLinker() const {
  534. return new tools::hexagon::Linker(*this);
  535. }
  536. unsigned HexagonToolChain::getOptimizationLevel(
  537. const llvm::opt::ArgList &DriverArgs) const {
  538. // Copied in large part from lib/Frontend/CompilerInvocation.cpp.
  539. Arg *A = DriverArgs.getLastArg(options::OPT_O_Group);
  540. if (!A)
  541. return 0;
  542. if (A->getOption().matches(options::OPT_O0))
  543. return 0;
  544. if (A->getOption().matches(options::OPT_Ofast) ||
  545. A->getOption().matches(options::OPT_O4))
  546. return 3;
  547. assert(A->getNumValues() != 0);
  548. StringRef S(A->getValue());
  549. if (S == "s" || S == "z" || S.empty())
  550. return 2;
  551. if (S == "g")
  552. return 1;
  553. unsigned OptLevel;
  554. if (S.getAsInteger(10, OptLevel))
  555. return 0;
  556. return OptLevel;
  557. }
  558. void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
  559. ArgStringList &CC1Args,
  560. Action::OffloadKind) const {
  561. bool UseInitArrayDefault = getTriple().isMusl();
  562. if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
  563. options::OPT_fno_use_init_array,
  564. UseInitArrayDefault))
  565. CC1Args.push_back("-fno-use-init-array");
  566. if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
  567. CC1Args.push_back("-target-feature");
  568. CC1Args.push_back("+reserved-r19");
  569. }
  570. if (isAutoHVXEnabled(DriverArgs)) {
  571. CC1Args.push_back("-mllvm");
  572. CC1Args.push_back("-hexagon-autohvx");
  573. }
  574. }
  575. void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  576. ArgStringList &CC1Args) const {
  577. if (DriverArgs.hasArg(options::OPT_nostdinc))
  578. return;
  579. const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();
  580. const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();
  581. const Driver &D = getDriver();
  582. SmallString<128> ResourceDirInclude(D.ResourceDir);
  583. if (!IsELF) {
  584. llvm::sys::path::append(ResourceDirInclude, "include");
  585. if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&
  586. (!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))
  587. addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
  588. }
  589. if (DriverArgs.hasArg(options::OPT_nostdlibinc))
  590. return;
  591. const bool HasSysRoot = !D.SysRoot.empty();
  592. if (HasSysRoot) {
  593. SmallString<128> P(D.SysRoot);
  594. if (IsLinuxMusl)
  595. llvm::sys::path::append(P, "usr/include");
  596. else
  597. llvm::sys::path::append(P, "include");
  598. addExternCSystemInclude(DriverArgs, CC1Args, P.str());
  599. // LOCAL_INCLUDE_DIR
  600. addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");
  601. // TOOL_INCLUDE_DIR
  602. AddMultilibIncludeArgs(DriverArgs, CC1Args);
  603. }
  604. if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)
  605. addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
  606. if (HasSysRoot)
  607. return;
  608. std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
  609. D.PrefixDirs);
  610. addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
  611. }
  612. void HexagonToolChain::addLibCxxIncludePaths(
  613. const llvm::opt::ArgList &DriverArgs,
  614. llvm::opt::ArgStringList &CC1Args) const {
  615. const Driver &D = getDriver();
  616. if (!D.SysRoot.empty() && getTriple().isMusl())
  617. addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",
  618. DriverArgs, CC1Args);
  619. else if (getTriple().isMusl())
  620. addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
  621. CC1Args);
  622. else {
  623. std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
  624. addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
  625. DriverArgs, CC1Args);
  626. }
  627. }
  628. void HexagonToolChain::addLibStdCxxIncludePaths(
  629. const llvm::opt::ArgList &DriverArgs,
  630. llvm::opt::ArgStringList &CC1Args) const {
  631. const Driver &D = getDriver();
  632. std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
  633. addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
  634. DriverArgs, CC1Args);
  635. }
  636. ToolChain::CXXStdlibType
  637. HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
  638. Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
  639. if (!A) {
  640. if (getTriple().isMusl())
  641. return ToolChain::CST_Libcxx;
  642. else
  643. return ToolChain::CST_Libstdcxx;
  644. }
  645. StringRef Value = A->getValue();
  646. if (Value != "libstdc++" && Value != "libc++")
  647. getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
  648. if (Value == "libstdc++")
  649. return ToolChain::CST_Libstdcxx;
  650. else if (Value == "libc++")
  651. return ToolChain::CST_Libcxx;
  652. else
  653. return ToolChain::CST_Libstdcxx;
  654. }
  655. bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
  656. if (Arg *A = Args.getLastArg(options::OPT_fvectorize,
  657. options::OPT_fno_vectorize))
  658. return A->getOption().matches(options::OPT_fvectorize);
  659. return false;
  660. }
  661. //
  662. // Returns the default CPU for Hexagon. This is the default compilation target
  663. // if no Hexagon processor is selected at the command-line.
  664. //
  665. StringRef HexagonToolChain::GetDefaultCPU() {
  666. return "hexagonv60";
  667. }
  668. StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
  669. Arg *CpuArg = nullptr;
  670. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
  671. CpuArg = A;
  672. StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
  673. if (CPU.startswith("hexagon"))
  674. return CPU.substr(sizeof("hexagon") - 1);
  675. return CPU;
  676. }