RISCV.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. //===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- 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 "RISCV.h"
  9. #include "ToolChains/CommonArgs.h"
  10. #include "clang/Basic/CharInfo.h"
  11. #include "clang/Driver/Driver.h"
  12. #include "clang/Driver/DriverDiagnostic.h"
  13. #include "clang/Driver/Options.h"
  14. #include "llvm/ADT/Optional.h"
  15. #include "llvm/Option/ArgList.h"
  16. #include "llvm/Support/Error.h"
  17. #include "llvm/Support/RISCVISAInfo.h"
  18. #include "llvm/Support/TargetParser.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. using namespace clang::driver;
  21. using namespace clang::driver::tools;
  22. using namespace clang;
  23. using namespace llvm::opt;
  24. // Returns false if an error is diagnosed.
  25. static bool getArchFeatures(const Driver &D, StringRef Arch,
  26. std::vector<StringRef> &Features,
  27. const ArgList &Args) {
  28. bool EnableExperimentalExtensions =
  29. Args.hasArg(options::OPT_menable_experimental_extensions);
  30. auto ISAInfo =
  31. llvm::RISCVISAInfo::parseArchString(Arch, EnableExperimentalExtensions);
  32. if (!ISAInfo) {
  33. handleAllErrors(ISAInfo.takeError(), [&](llvm::StringError &ErrMsg) {
  34. D.Diag(diag::err_drv_invalid_riscv_arch_name)
  35. << Arch << ErrMsg.getMessage();
  36. });
  37. return false;
  38. }
  39. (*ISAInfo)->toFeatures(
  40. Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); });
  41. return true;
  42. }
  43. // Get features except standard extension feature
  44. static void getRISCFeaturesFromMcpu(const Driver &D, const llvm::Triple &Triple,
  45. const llvm::opt::ArgList &Args,
  46. const llvm::opt::Arg *A, StringRef Mcpu,
  47. std::vector<StringRef> &Features) {
  48. bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64);
  49. llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu);
  50. if (!llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) ||
  51. !llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features)) {
  52. D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
  53. }
  54. }
  55. void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
  56. const ArgList &Args,
  57. std::vector<StringRef> &Features) {
  58. StringRef MArch = getRISCVArch(Args, Triple);
  59. if (!getArchFeatures(D, MArch, Features, Args))
  60. return;
  61. // If users give march and mcpu, get std extension feature from MArch
  62. // and other features (ex. mirco architecture feature) from mcpu
  63. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
  64. getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features);
  65. // Handle features corresponding to "-ffixed-X" options
  66. if (Args.hasArg(options::OPT_ffixed_x1))
  67. Features.push_back("+reserve-x1");
  68. if (Args.hasArg(options::OPT_ffixed_x2))
  69. Features.push_back("+reserve-x2");
  70. if (Args.hasArg(options::OPT_ffixed_x3))
  71. Features.push_back("+reserve-x3");
  72. if (Args.hasArg(options::OPT_ffixed_x4))
  73. Features.push_back("+reserve-x4");
  74. if (Args.hasArg(options::OPT_ffixed_x5))
  75. Features.push_back("+reserve-x5");
  76. if (Args.hasArg(options::OPT_ffixed_x6))
  77. Features.push_back("+reserve-x6");
  78. if (Args.hasArg(options::OPT_ffixed_x7))
  79. Features.push_back("+reserve-x7");
  80. if (Args.hasArg(options::OPT_ffixed_x8))
  81. Features.push_back("+reserve-x8");
  82. if (Args.hasArg(options::OPT_ffixed_x9))
  83. Features.push_back("+reserve-x9");
  84. if (Args.hasArg(options::OPT_ffixed_x10))
  85. Features.push_back("+reserve-x10");
  86. if (Args.hasArg(options::OPT_ffixed_x11))
  87. Features.push_back("+reserve-x11");
  88. if (Args.hasArg(options::OPT_ffixed_x12))
  89. Features.push_back("+reserve-x12");
  90. if (Args.hasArg(options::OPT_ffixed_x13))
  91. Features.push_back("+reserve-x13");
  92. if (Args.hasArg(options::OPT_ffixed_x14))
  93. Features.push_back("+reserve-x14");
  94. if (Args.hasArg(options::OPT_ffixed_x15))
  95. Features.push_back("+reserve-x15");
  96. if (Args.hasArg(options::OPT_ffixed_x16))
  97. Features.push_back("+reserve-x16");
  98. if (Args.hasArg(options::OPT_ffixed_x17))
  99. Features.push_back("+reserve-x17");
  100. if (Args.hasArg(options::OPT_ffixed_x18))
  101. Features.push_back("+reserve-x18");
  102. if (Args.hasArg(options::OPT_ffixed_x19))
  103. Features.push_back("+reserve-x19");
  104. if (Args.hasArg(options::OPT_ffixed_x20))
  105. Features.push_back("+reserve-x20");
  106. if (Args.hasArg(options::OPT_ffixed_x21))
  107. Features.push_back("+reserve-x21");
  108. if (Args.hasArg(options::OPT_ffixed_x22))
  109. Features.push_back("+reserve-x22");
  110. if (Args.hasArg(options::OPT_ffixed_x23))
  111. Features.push_back("+reserve-x23");
  112. if (Args.hasArg(options::OPT_ffixed_x24))
  113. Features.push_back("+reserve-x24");
  114. if (Args.hasArg(options::OPT_ffixed_x25))
  115. Features.push_back("+reserve-x25");
  116. if (Args.hasArg(options::OPT_ffixed_x26))
  117. Features.push_back("+reserve-x26");
  118. if (Args.hasArg(options::OPT_ffixed_x27))
  119. Features.push_back("+reserve-x27");
  120. if (Args.hasArg(options::OPT_ffixed_x28))
  121. Features.push_back("+reserve-x28");
  122. if (Args.hasArg(options::OPT_ffixed_x29))
  123. Features.push_back("+reserve-x29");
  124. if (Args.hasArg(options::OPT_ffixed_x30))
  125. Features.push_back("+reserve-x30");
  126. if (Args.hasArg(options::OPT_ffixed_x31))
  127. Features.push_back("+reserve-x31");
  128. // -mrelax is default, unless -mno-relax is specified.
  129. if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
  130. Features.push_back("+relax");
  131. else
  132. Features.push_back("-relax");
  133. // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
  134. // specified.
  135. if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false))
  136. Features.push_back("+save-restore");
  137. else
  138. Features.push_back("-save-restore");
  139. // Now add any that the user explicitly requested on the command line,
  140. // which may override the defaults.
  141. handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
  142. }
  143. StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
  144. assert((Triple.getArch() == llvm::Triple::riscv32 ||
  145. Triple.getArch() == llvm::Triple::riscv64) &&
  146. "Unexpected triple");
  147. // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
  148. // configured using `--with-abi=`, then the logic for the default choice is
  149. // defined in config.gcc. This function is based on the logic in GCC 9.2.0.
  150. //
  151. // The logic used in GCC 9.2.0 is the following, in order:
  152. // 1. Explicit choices using `--with-abi=`
  153. // 2. A default based on `--with-arch=`, if provided
  154. // 3. A default based on the target triple's arch
  155. //
  156. // The logic in config.gcc is a little circular but it is not inconsistent.
  157. //
  158. // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
  159. // and `-mabi=` respectively instead.
  160. //
  161. // In order to make chosing logic more clear, Clang uses the following logic,
  162. // in order:
  163. // 1. Explicit choices using `-mabi=`
  164. // 2. A default based on the architecture as determined by getRISCVArch
  165. // 3. Choose a default based on the triple
  166. // 1. If `-mabi=` is specified, use it.
  167. if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
  168. return A->getValue();
  169. // 2. Choose a default based on the target architecture.
  170. //
  171. // rv32g | rv32*d -> ilp32d
  172. // rv32e -> ilp32e
  173. // rv32* -> ilp32
  174. // rv64g | rv64*d -> lp64d
  175. // rv64* -> lp64
  176. StringRef Arch = getRISCVArch(Args, Triple);
  177. auto ParseResult = llvm::RISCVISAInfo::parseArchString(
  178. Arch, /* EnableExperimentalExtension */ true);
  179. if (!ParseResult)
  180. // Ignore parsing error, just go 3rd step.
  181. consumeError(ParseResult.takeError());
  182. else
  183. return llvm::RISCV::computeDefaultABIFromArch(**ParseResult);
  184. // 3. Choose a default based on the triple
  185. //
  186. // We deviate from GCC's defaults here:
  187. // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
  188. // - On all other OSs we use the double floating point calling convention.
  189. if (Triple.getArch() == llvm::Triple::riscv32) {
  190. if (Triple.getOS() == llvm::Triple::UnknownOS)
  191. return "ilp32";
  192. else
  193. return "ilp32d";
  194. } else {
  195. if (Triple.getOS() == llvm::Triple::UnknownOS)
  196. return "lp64";
  197. else
  198. return "lp64d";
  199. }
  200. }
  201. StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
  202. const llvm::Triple &Triple) {
  203. assert((Triple.getArch() == llvm::Triple::riscv32 ||
  204. Triple.getArch() == llvm::Triple::riscv64) &&
  205. "Unexpected triple");
  206. // GCC's logic around choosing a default `-march=` is complex. If GCC is not
  207. // configured using `--with-arch=`, then the logic for the default choice is
  208. // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
  209. // deviate from GCC's default on additional `-mcpu` option (GCC does not
  210. // support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march`
  211. // nor `-mabi` is specified.
  212. //
  213. // The logic used in GCC 9.2.0 is the following, in order:
  214. // 1. Explicit choices using `--with-arch=`
  215. // 2. A default based on `--with-abi=`, if provided
  216. // 3. A default based on the target triple's arch
  217. //
  218. // The logic in config.gcc is a little circular but it is not inconsistent.
  219. //
  220. // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
  221. // and `-mabi=` respectively instead.
  222. //
  223. // Clang uses the following logic, in order:
  224. // 1. Explicit choices using `-march=`
  225. // 2. Based on `-mcpu` if the target CPU has a default ISA string
  226. // 3. A default based on `-mabi`, if provided
  227. // 4. A default based on the target triple's arch
  228. //
  229. // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
  230. // instead of `rv{XLEN}gc` though they are (currently) equivalent.
  231. // 1. If `-march=` is specified, use it.
  232. if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
  233. return A->getValue();
  234. // 2. Get march (isa string) based on `-mcpu=`
  235. if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
  236. StringRef MArch = llvm::RISCV::getMArchFromMcpu(A->getValue());
  237. // Bypass if target cpu's default march is empty.
  238. if (MArch != "")
  239. return MArch;
  240. }
  241. // 3. Choose a default based on `-mabi=`
  242. //
  243. // ilp32e -> rv32e
  244. // ilp32 | ilp32f | ilp32d -> rv32imafdc
  245. // lp64 | lp64f | lp64d -> rv64imafdc
  246. if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
  247. StringRef MABI = A->getValue();
  248. if (MABI.equals_insensitive("ilp32e"))
  249. return "rv32e";
  250. else if (MABI.startswith_insensitive("ilp32"))
  251. return "rv32imafdc";
  252. else if (MABI.startswith_insensitive("lp64"))
  253. return "rv64imafdc";
  254. }
  255. // 4. Choose a default based on the triple
  256. //
  257. // We deviate from GCC's defaults here:
  258. // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
  259. // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
  260. if (Triple.getArch() == llvm::Triple::riscv32) {
  261. if (Triple.getOS() == llvm::Triple::UnknownOS)
  262. return "rv32imac";
  263. else
  264. return "rv32imafdc";
  265. } else {
  266. if (Triple.getOS() == llvm::Triple::UnknownOS)
  267. return "rv64imac";
  268. else
  269. return "rv64imafdc";
  270. }
  271. }