Myriad.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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, Args.MakeArgString(Exec),
  72. CmdArgs, Inputs));
  73. }
  74. void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
  75. const InputInfo &Output,
  76. const InputInfoList &Inputs,
  77. const ArgList &Args,
  78. const char *LinkingOutput) const {
  79. ArgStringList CmdArgs;
  80. assert(Inputs.size() == 1);
  81. const InputInfo &II = Inputs[0];
  82. assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
  83. assert(Output.getType() == types::TY_Object);
  84. CmdArgs.push_back("-no6thSlotCompression");
  85. const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
  86. if (CPUArg)
  87. CmdArgs.push_back(
  88. Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue())));
  89. CmdArgs.push_back("-noSPrefixing");
  90. CmdArgs.push_back("-a"); // Mystery option.
  91. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  92. for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) {
  93. A->claim();
  94. CmdArgs.push_back(
  95. Args.MakeArgString(std::string("-i:") + A->getValue(0)));
  96. }
  97. CmdArgs.push_back(II.getFilename());
  98. CmdArgs.push_back(
  99. Args.MakeArgString(std::string("-o:") + Output.getFilename()));
  100. std::string Exec =
  101. Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
  102. C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
  103. CmdArgs, Inputs));
  104. }
  105. void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  106. const InputInfo &Output,
  107. const InputInfoList &Inputs,
  108. const ArgList &Args,
  109. const char *LinkingOutput) const {
  110. const auto &TC =
  111. static_cast<const toolchains::MyriadToolChain &>(getToolChain());
  112. const llvm::Triple &T = TC.getTriple();
  113. ArgStringList CmdArgs;
  114. bool UseStartfiles =
  115. !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
  116. bool UseDefaultLibs =
  117. !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
  118. // Silence warning if the args contain both -nostdlib and -stdlib=.
  119. Args.getLastArg(options::OPT_stdlib_EQ);
  120. if (T.getArch() == llvm::Triple::sparc)
  121. CmdArgs.push_back("-EB");
  122. else // SHAVE assumes little-endian, and sparcel is expressly so.
  123. CmdArgs.push_back("-EL");
  124. // The remaining logic is mostly like gnutools::Linker::ConstructJob,
  125. // but we never pass through a --sysroot option and various other bits.
  126. // For example, there are no sanitizers (yet) nor gold linker.
  127. // Eat some arguments that may be present but have no effect.
  128. Args.ClaimAllArgs(options::OPT_g_Group);
  129. Args.ClaimAllArgs(options::OPT_w);
  130. Args.ClaimAllArgs(options::OPT_static_libgcc);
  131. if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
  132. CmdArgs.push_back("-s");
  133. CmdArgs.push_back("-o");
  134. CmdArgs.push_back(Output.getFilename());
  135. if (UseStartfiles) {
  136. // If you want startfiles, it means you want the builtin crti and crtbegin,
  137. // but not crt0. Myriad link commands provide their own crt0.o as needed.
  138. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o")));
  139. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
  140. }
  141. Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
  142. options::OPT_e, options::OPT_s, options::OPT_t,
  143. options::OPT_Z_Flag, options::OPT_r});
  144. TC.AddFilePathLibArgs(Args, CmdArgs);
  145. bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
  146. AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  147. if (UseDefaultLibs) {
  148. if (NeedsSanitizerDeps)
  149. linkSanitizerRuntimeDeps(TC, CmdArgs);
  150. if (C.getDriver().CCCIsCXX()) {
  151. if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
  152. CmdArgs.push_back("-lc++");
  153. CmdArgs.push_back("-lc++abi");
  154. } else
  155. CmdArgs.push_back("-lstdc++");
  156. }
  157. if (T.getOS() == llvm::Triple::RTEMS) {
  158. CmdArgs.push_back("--start-group");
  159. CmdArgs.push_back("-lc");
  160. CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
  161. // You must provide your own "-L" option to enable finding these.
  162. CmdArgs.push_back("-lrtemscpu");
  163. CmdArgs.push_back("-lrtemsbsp");
  164. CmdArgs.push_back("--end-group");
  165. } else {
  166. CmdArgs.push_back("-lc");
  167. CmdArgs.push_back("-lgcc");
  168. }
  169. }
  170. if (UseStartfiles) {
  171. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
  172. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o")));
  173. }
  174. std::string Exec =
  175. Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld"));
  176. C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
  177. CmdArgs, Inputs));
  178. }
  179. MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
  180. const ArgList &Args)
  181. : Generic_ELF(D, Triple, Args) {
  182. // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
  183. // 'sparc-myriad--elf' (note the unknown OS) as the canonical triple.
  184. // This won't work to find gcc. Instead we give the installation detector an
  185. // extra triple, which is preferable to further hacks of the logic that at
  186. // present is based solely on getArch(). In particular, it would be wrong to
  187. // choose the myriad installation when targeting a non-myriad sparc install.
  188. switch (Triple.getArch()) {
  189. default:
  190. D.Diag(clang::diag::err_target_unsupported_arch)
  191. << Triple.getArchName() << "myriad";
  192. LLVM_FALLTHROUGH;
  193. case llvm::Triple::shave:
  194. return;
  195. case llvm::Triple::sparc:
  196. case llvm::Triple::sparcel:
  197. GCCInstallation.init(Triple, Args, {"sparc-myriad-rtems"});
  198. }
  199. if (GCCInstallation.isValid()) {
  200. // This directory contains crt{i,n,begin,end}.o as well as libgcc.
  201. // These files are tied to a particular version of gcc.
  202. SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath());
  203. addPathIfExists(D, CompilerSupportDir, getFilePaths());
  204. }
  205. // libstd++ and libc++ must both be found in this one place.
  206. addPathIfExists(D, D.Dir + "/../sparc-myriad-rtems/lib", getFilePaths());
  207. }
  208. MyriadToolChain::~MyriadToolChain() {}
  209. void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  210. ArgStringList &CC1Args) const {
  211. if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
  212. addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
  213. }
  214. void MyriadToolChain::addLibCxxIncludePaths(
  215. const llvm::opt::ArgList &DriverArgs,
  216. llvm::opt::ArgStringList &CC1Args) const {
  217. std::string Path(getDriver().getInstalledDir());
  218. addSystemInclude(DriverArgs, CC1Args, Path + "/../include/c++/v1");
  219. }
  220. void MyriadToolChain::addLibStdCxxIncludePaths(
  221. const llvm::opt::ArgList &DriverArgs,
  222. llvm::opt::ArgStringList &CC1Args) const {
  223. StringRef LibDir = GCCInstallation.getParentLibPath();
  224. const GCCVersion &Version = GCCInstallation.getVersion();
  225. StringRef TripleStr = GCCInstallation.getTriple().str();
  226. const Multilib &Multilib = GCCInstallation.getMultilib();
  227. addLibStdCXXIncludePaths(
  228. LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
  229. "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
  230. }
  231. // MyriadToolChain handles several triples:
  232. // {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
  233. Tool *MyriadToolChain::SelectTool(const JobAction &JA) const {
  234. // The inherited method works fine if not targeting the SHAVE.
  235. if (!isShaveCompilation(getTriple()))
  236. return ToolChain::SelectTool(JA);
  237. switch (JA.getKind()) {
  238. case Action::PreprocessJobClass:
  239. case Action::CompileJobClass:
  240. if (!Compiler)
  241. Compiler.reset(new tools::SHAVE::Compiler(*this));
  242. return Compiler.get();
  243. case Action::AssembleJobClass:
  244. if (!Assembler)
  245. Assembler.reset(new tools::SHAVE::Assembler(*this));
  246. return Assembler.get();
  247. default:
  248. return ToolChain::getTool(JA.getKind());
  249. }
  250. }
  251. Tool *MyriadToolChain::buildLinker() const {
  252. return new tools::Myriad::Linker(*this);
  253. }
  254. SanitizerMask MyriadToolChain::getSupportedSanitizers() const {
  255. return SanitizerKind::Address;
  256. }