Myriad.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. //===--- Myriad.cpp - Myriad 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 "Myriad.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/Options.h"
  14. #include "llvm/Option/ArgList.h"
  15. using namespace clang::driver;
  16. using namespace clang::driver::toolchains;
  17. using namespace clang;
  18. using namespace llvm::opt;
  19. using tools::addPathIfExists;
  20. void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
  21. const InputInfo &Output,
  22. const InputInfoList &Inputs,
  23. const ArgList &Args,
  24. const char *LinkingOutput) const {
  25. ArgStringList CmdArgs;
  26. assert(Inputs.size() == 1);
  27. const InputInfo &II = Inputs[0];
  28. assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX ||
  29. II.getType() == types::TY_PP_CXX);
  30. if (JA.getKind() == Action::PreprocessJobClass) {
  31. Args.ClaimAllArgs();
  32. CmdArgs.push_back("-E");
  33. } else {
  34. assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
  35. CmdArgs.push_back("-S");
  36. CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
  37. }
  38. CmdArgs.push_back("-DMYRIAD2");
  39. // Append all -I, -iquote, -isystem paths, defines/undefines, 'f'
  40. // flags, 'g' flags, 'M' flags, optimize flags, warning options,
  41. // mcpu flags, mllvm flags, and Xclang flags.
  42. // These are spelled the same way in clang and moviCompile.
  43. Args.AddAllArgsExcept(
  44. CmdArgs,
  45. {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ,
  46. options::OPT_D, options::OPT_U, options::OPT_f_Group,
  47. options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group,
  48. options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ,
  49. options::OPT_mllvm, options::OPT_Xclang},
  50. {options::OPT_fno_split_dwarf_inlining});
  51. Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present.
  52. // If we're producing a dependency file, and assembly is the final action,
  53. // then the name of the target in the dependency file should be the '.o'
  54. // file, not the '.s' file produced by this step. For example, instead of
  55. // /tmp/mumble.s: mumble.c .../someheader.h
  56. // the filename on the lefthand side should be "mumble.o"
  57. if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) &&
  58. C.getActions().size() == 1 &&
  59. C.getActions()[0]->getKind() == Action::AssembleJobClass) {
  60. Arg *A = Args.getLastArg(options::OPT_o);
  61. if (A) {
  62. CmdArgs.push_back("-MT");
  63. CmdArgs.push_back(Args.MakeArgString(A->getValue()));
  64. }
  65. }
  66. CmdArgs.push_back(II.getFilename());
  67. CmdArgs.push_back("-o");
  68. CmdArgs.push_back(Output.getFilename());
  69. std::string Exec =
  70. Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
  71. C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
  72. Args.MakeArgString(Exec), CmdArgs,
  73. Inputs, Output));
  74. }
  75. void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
  76. const InputInfo &Output,
  77. const InputInfoList &Inputs,
  78. const ArgList &Args,
  79. const char *LinkingOutput) const {
  80. ArgStringList CmdArgs;
  81. assert(Inputs.size() == 1);
  82. const InputInfo &II = Inputs[0];
  83. assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
  84. assert(Output.getType() == types::TY_Object);
  85. CmdArgs.push_back("-no6thSlotCompression");
  86. const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
  87. if (CPUArg)
  88. CmdArgs.push_back(
  89. Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue())));
  90. CmdArgs.push_back("-noSPrefixing");
  91. CmdArgs.push_back("-a"); // Mystery option.
  92. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  93. for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) {
  94. A->claim();
  95. CmdArgs.push_back(
  96. Args.MakeArgString(std::string("-i:") + A->getValue(0)));
  97. }
  98. CmdArgs.push_back(II.getFilename());
  99. CmdArgs.push_back(
  100. Args.MakeArgString(std::string("-o:") + Output.getFilename()));
  101. std::string Exec =
  102. Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
  103. C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
  104. Args.MakeArgString(Exec), CmdArgs,
  105. Inputs, Output));
  106. }
  107. void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  108. const InputInfo &Output,
  109. const InputInfoList &Inputs,
  110. const ArgList &Args,
  111. const char *LinkingOutput) const {
  112. const auto &TC =
  113. static_cast<const toolchains::MyriadToolChain &>(getToolChain());
  114. const llvm::Triple &T = TC.getTriple();
  115. ArgStringList CmdArgs;
  116. bool UseStartfiles =
  117. !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
  118. bool UseDefaultLibs =
  119. !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
  120. // Silence warning if the args contain both -nostdlib and -stdlib=.
  121. Args.getLastArg(options::OPT_stdlib_EQ);
  122. if (T.getArch() == llvm::Triple::sparc)
  123. CmdArgs.push_back("-EB");
  124. else // SHAVE assumes little-endian, and sparcel is expressly so.
  125. CmdArgs.push_back("-EL");
  126. // The remaining logic is mostly like gnutools::Linker::ConstructJob,
  127. // but we never pass through a --sysroot option and various other bits.
  128. // For example, there are no sanitizers (yet) nor gold linker.
  129. // Eat some arguments that may be present but have no effect.
  130. Args.ClaimAllArgs(options::OPT_g_Group);
  131. Args.ClaimAllArgs(options::OPT_w);
  132. Args.ClaimAllArgs(options::OPT_static_libgcc);
  133. if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
  134. CmdArgs.push_back("-s");
  135. CmdArgs.push_back("-o");
  136. CmdArgs.push_back(Output.getFilename());
  137. if (UseStartfiles) {
  138. // If you want startfiles, it means you want the builtin crti and crtbegin,
  139. // but not crt0. Myriad link commands provide their own crt0.o as needed.
  140. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o")));
  141. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
  142. }
  143. Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
  144. options::OPT_e, options::OPT_s, options::OPT_t,
  145. options::OPT_Z_Flag, options::OPT_r});
  146. TC.AddFilePathLibArgs(Args, CmdArgs);
  147. bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
  148. AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  149. if (UseDefaultLibs) {
  150. if (NeedsSanitizerDeps)
  151. linkSanitizerRuntimeDeps(TC, CmdArgs);
  152. if (C.getDriver().CCCIsCXX()) {
  153. if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
  154. CmdArgs.push_back("-lc++");
  155. CmdArgs.push_back("-lc++abi");
  156. } else
  157. CmdArgs.push_back("-lstdc++");
  158. }
  159. if (T.getOS() == llvm::Triple::RTEMS) {
  160. CmdArgs.push_back("--start-group");
  161. CmdArgs.push_back("-lc");
  162. CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
  163. // You must provide your own "-L" option to enable finding these.
  164. CmdArgs.push_back("-lrtemscpu");
  165. CmdArgs.push_back("-lrtemsbsp");
  166. CmdArgs.push_back("--end-group");
  167. } else {
  168. CmdArgs.push_back("-lc");
  169. CmdArgs.push_back("-lgcc");
  170. }
  171. }
  172. if (UseStartfiles) {
  173. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
  174. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o")));
  175. }
  176. std::string Exec =
  177. Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld"));
  178. C.addCommand(std::make_unique<Command>(
  179. JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Exec),
  180. CmdArgs, Inputs, Output));
  181. }
  182. MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
  183. const ArgList &Args)
  184. : Generic_ELF(D, Triple, Args) {
  185. // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
  186. // 'sparc-myriad--elf' (note the unknown OS) as the canonical triple.
  187. // This won't work to find gcc. Instead we give the installation detector an
  188. // extra triple, which is preferable to further hacks of the logic that at
  189. // present is based solely on getArch(). In particular, it would be wrong to
  190. // choose the myriad installation when targeting a non-myriad sparc install.
  191. switch (Triple.getArch()) {
  192. default:
  193. D.Diag(clang::diag::err_target_unsupported_arch)
  194. << Triple.getArchName() << "myriad";
  195. [[fallthrough]];
  196. case llvm::Triple::shave:
  197. return;
  198. case llvm::Triple::sparc:
  199. case llvm::Triple::sparcel:
  200. GCCInstallation.init(Triple, Args, {"sparc-myriad-rtems"});
  201. }
  202. if (GCCInstallation.isValid()) {
  203. // This directory contains crt{i,n,begin,end}.o as well as libgcc.
  204. // These files are tied to a particular version of gcc.
  205. SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath());
  206. addPathIfExists(D, CompilerSupportDir, getFilePaths());
  207. }
  208. // libstd++ and libc++ must both be found in this one place.
  209. addPathIfExists(D, D.Dir + "/../sparc-myriad-rtems/lib", getFilePaths());
  210. }
  211. MyriadToolChain::~MyriadToolChain() {}
  212. void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  213. ArgStringList &CC1Args) const {
  214. if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
  215. addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
  216. }
  217. void MyriadToolChain::addLibCxxIncludePaths(
  218. const llvm::opt::ArgList &DriverArgs,
  219. llvm::opt::ArgStringList &CC1Args) const {
  220. std::string Path(getDriver().getInstalledDir());
  221. addSystemInclude(DriverArgs, CC1Args, Path + "/../include/c++/v1");
  222. }
  223. void MyriadToolChain::addLibStdCxxIncludePaths(
  224. const llvm::opt::ArgList &DriverArgs,
  225. llvm::opt::ArgStringList &CC1Args) const {
  226. StringRef LibDir = GCCInstallation.getParentLibPath();
  227. const GCCVersion &Version = GCCInstallation.getVersion();
  228. StringRef TripleStr = GCCInstallation.getTriple().str();
  229. const Multilib &Multilib = GCCInstallation.getMultilib();
  230. addLibStdCXXIncludePaths(
  231. LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
  232. TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args);
  233. }
  234. // MyriadToolChain handles several triples:
  235. // {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
  236. Tool *MyriadToolChain::SelectTool(const JobAction &JA) const {
  237. // The inherited method works fine if not targeting the SHAVE.
  238. if (!isShaveCompilation(getTriple()))
  239. return ToolChain::SelectTool(JA);
  240. switch (JA.getKind()) {
  241. case Action::PreprocessJobClass:
  242. case Action::CompileJobClass:
  243. if (!Compiler)
  244. Compiler.reset(new tools::SHAVE::Compiler(*this));
  245. return Compiler.get();
  246. case Action::AssembleJobClass:
  247. if (!Assembler)
  248. Assembler.reset(new tools::SHAVE::Assembler(*this));
  249. return Assembler.get();
  250. default:
  251. return ToolChain::getTool(JA.getKind());
  252. }
  253. }
  254. Tool *MyriadToolChain::buildLinker() const {
  255. return new tools::Myriad::Linker(*this);
  256. }
  257. SanitizerMask MyriadToolChain::getSupportedSanitizers() const {
  258. return SanitizerKind::Address;
  259. }