WebAssembly.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. //===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
  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. //
  9. // This file implements WebAssembly TargetInfo objects.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "WebAssembly.h"
  13. #include "Targets.h"
  14. #include "clang/Basic/Builtins.h"
  15. #include "clang/Basic/Diagnostic.h"
  16. #include "clang/Basic/TargetBuiltins.h"
  17. #include "llvm/ADT/StringSwitch.h"
  18. using namespace clang;
  19. using namespace clang::targets;
  20. static constexpr Builtin::Info BuiltinInfo[] = {
  21. #define BUILTIN(ID, TYPE, ATTRS) \
  22. {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
  23. #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
  24. {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
  25. #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
  26. {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
  27. #include "clang/Basic/BuiltinsWebAssembly.def"
  28. };
  29. static constexpr llvm::StringLiteral ValidCPUNames[] = {
  30. {"mvp"}, {"bleeding-edge"}, {"generic"}};
  31. StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
  32. bool WebAssemblyTargetInfo::setABI(const std::string &Name) {
  33. if (Name != "mvp" && Name != "experimental-mv")
  34. return false;
  35. ABI = Name;
  36. return true;
  37. }
  38. bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
  39. return llvm::StringSwitch<bool>(Feature)
  40. .Case("simd128", SIMDLevel >= SIMD128)
  41. .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
  42. .Case("nontrapping-fptoint", HasNontrappingFPToInt)
  43. .Case("sign-ext", HasSignExt)
  44. .Case("exception-handling", HasExceptionHandling)
  45. .Case("bulk-memory", HasBulkMemory)
  46. .Case("atomics", HasAtomics)
  47. .Case("mutable-globals", HasMutableGlobals)
  48. .Case("multivalue", HasMultivalue)
  49. .Case("tail-call", HasTailCall)
  50. .Case("reference-types", HasReferenceTypes)
  51. .Case("extended-const", HasExtendedConst)
  52. .Default(false);
  53. }
  54. bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
  55. return llvm::is_contained(ValidCPUNames, Name);
  56. }
  57. void WebAssemblyTargetInfo::fillValidCPUList(
  58. SmallVectorImpl<StringRef> &Values) const {
  59. Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
  60. }
  61. void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
  62. MacroBuilder &Builder) const {
  63. defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
  64. if (SIMDLevel >= SIMD128)
  65. Builder.defineMacro("__wasm_simd128__");
  66. if (SIMDLevel >= RelaxedSIMD)
  67. Builder.defineMacro("__wasm_relaxed_simd__");
  68. if (HasNontrappingFPToInt)
  69. Builder.defineMacro("__wasm_nontrapping_fptoint__");
  70. if (HasSignExt)
  71. Builder.defineMacro("__wasm_sign_ext__");
  72. if (HasExceptionHandling)
  73. Builder.defineMacro("__wasm_exception_handling__");
  74. if (HasBulkMemory)
  75. Builder.defineMacro("__wasm_bulk_memory__");
  76. if (HasAtomics)
  77. Builder.defineMacro("__wasm_atomics__");
  78. if (HasMutableGlobals)
  79. Builder.defineMacro("__wasm_mutable_globals__");
  80. if (HasMultivalue)
  81. Builder.defineMacro("__wasm_multivalue__");
  82. if (HasTailCall)
  83. Builder.defineMacro("__wasm_tail_call__");
  84. if (HasReferenceTypes)
  85. Builder.defineMacro("__wasm_reference_types__");
  86. if (HasExtendedConst)
  87. Builder.defineMacro("__wasm_extended_const__");
  88. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
  89. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
  90. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
  91. Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
  92. }
  93. void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
  94. SIMDEnum Level, bool Enabled) {
  95. if (Enabled) {
  96. switch (Level) {
  97. case RelaxedSIMD:
  98. Features["relaxed-simd"] = true;
  99. [[fallthrough]];
  100. case SIMD128:
  101. Features["simd128"] = true;
  102. [[fallthrough]];
  103. case NoSIMD:
  104. break;
  105. }
  106. return;
  107. }
  108. switch (Level) {
  109. case NoSIMD:
  110. case SIMD128:
  111. Features["simd128"] = false;
  112. [[fallthrough]];
  113. case RelaxedSIMD:
  114. Features["relaxed-simd"] = false;
  115. break;
  116. }
  117. }
  118. void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
  119. StringRef Name,
  120. bool Enabled) const {
  121. if (Name == "simd128")
  122. setSIMDLevel(Features, SIMD128, Enabled);
  123. else if (Name == "relaxed-simd")
  124. setSIMDLevel(Features, RelaxedSIMD, Enabled);
  125. else
  126. Features[Name] = Enabled;
  127. }
  128. bool WebAssemblyTargetInfo::initFeatureMap(
  129. llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
  130. const std::vector<std::string> &FeaturesVec) const {
  131. if (CPU == "bleeding-edge") {
  132. Features["nontrapping-fptoint"] = true;
  133. Features["sign-ext"] = true;
  134. Features["bulk-memory"] = true;
  135. Features["atomics"] = true;
  136. Features["mutable-globals"] = true;
  137. Features["tail-call"] = true;
  138. setSIMDLevel(Features, SIMD128, true);
  139. } else if (CPU == "generic") {
  140. Features["sign-ext"] = true;
  141. Features["mutable-globals"] = true;
  142. }
  143. return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
  144. }
  145. bool WebAssemblyTargetInfo::handleTargetFeatures(
  146. std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
  147. for (const auto &Feature : Features) {
  148. if (Feature == "+simd128") {
  149. SIMDLevel = std::max(SIMDLevel, SIMD128);
  150. continue;
  151. }
  152. if (Feature == "-simd128") {
  153. SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
  154. continue;
  155. }
  156. if (Feature == "+relaxed-simd") {
  157. SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
  158. continue;
  159. }
  160. if (Feature == "-relaxed-simd") {
  161. SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
  162. continue;
  163. }
  164. if (Feature == "+nontrapping-fptoint") {
  165. HasNontrappingFPToInt = true;
  166. continue;
  167. }
  168. if (Feature == "-nontrapping-fptoint") {
  169. HasNontrappingFPToInt = false;
  170. continue;
  171. }
  172. if (Feature == "+sign-ext") {
  173. HasSignExt = true;
  174. continue;
  175. }
  176. if (Feature == "-sign-ext") {
  177. HasSignExt = false;
  178. continue;
  179. }
  180. if (Feature == "+exception-handling") {
  181. HasExceptionHandling = true;
  182. continue;
  183. }
  184. if (Feature == "-exception-handling") {
  185. HasExceptionHandling = false;
  186. continue;
  187. }
  188. if (Feature == "+bulk-memory") {
  189. HasBulkMemory = true;
  190. continue;
  191. }
  192. if (Feature == "-bulk-memory") {
  193. HasBulkMemory = false;
  194. continue;
  195. }
  196. if (Feature == "+atomics") {
  197. HasAtomics = true;
  198. continue;
  199. }
  200. if (Feature == "-atomics") {
  201. HasAtomics = false;
  202. continue;
  203. }
  204. if (Feature == "+mutable-globals") {
  205. HasMutableGlobals = true;
  206. continue;
  207. }
  208. if (Feature == "-mutable-globals") {
  209. HasMutableGlobals = false;
  210. continue;
  211. }
  212. if (Feature == "+multivalue") {
  213. HasMultivalue = true;
  214. continue;
  215. }
  216. if (Feature == "-multivalue") {
  217. HasMultivalue = false;
  218. continue;
  219. }
  220. if (Feature == "+tail-call") {
  221. HasTailCall = true;
  222. continue;
  223. }
  224. if (Feature == "-tail-call") {
  225. HasTailCall = false;
  226. continue;
  227. }
  228. if (Feature == "+reference-types") {
  229. HasReferenceTypes = true;
  230. continue;
  231. }
  232. if (Feature == "-reference-types") {
  233. HasReferenceTypes = false;
  234. continue;
  235. }
  236. if (Feature == "+extended-const") {
  237. HasExtendedConst = true;
  238. continue;
  239. }
  240. if (Feature == "-extended-const") {
  241. HasExtendedConst = false;
  242. continue;
  243. }
  244. Diags.Report(diag::err_opt_not_valid_with_opt)
  245. << Feature << "-target-feature";
  246. return false;
  247. }
  248. return true;
  249. }
  250. ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
  251. return llvm::ArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
  252. Builtin::FirstTSBuiltin);
  253. }
  254. void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
  255. LangOptions &Opts) {
  256. TargetInfo::adjust(Diags, Opts);
  257. // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
  258. // or __STDCPP_THREADS__ if we will eventually end up stripping atomics
  259. // because they are unsupported.
  260. if (!HasAtomics || !HasBulkMemory) {
  261. Opts.POSIXThreads = false;
  262. Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
  263. Opts.ThreadsafeStatics = false;
  264. }
  265. }
  266. void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
  267. MacroBuilder &Builder) const {
  268. WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
  269. defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
  270. }
  271. void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
  272. MacroBuilder &Builder) const {
  273. WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
  274. defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
  275. }