WebAssembly.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
  21. #define BUILTIN(ID, TYPE, ATTRS) \
  22. {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
  23. #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
  24. {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
  25. #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
  26. {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
  27. #include "clang/Basic/BuiltinsWebAssembly.def"
  28. };
  29. static constexpr llvm::StringLiteral ValidCPUNames[] = {
  30. {"mvp"}, {"bleeding-edge"}, {"generic"}};
  31. bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
  32. return llvm::StringSwitch<bool>(Feature)
  33. .Case("simd128", SIMDLevel >= SIMD128)
  34. .Case("unimplemented-simd128", SIMDLevel >= UnimplementedSIMD128)
  35. .Case("nontrapping-fptoint", HasNontrappingFPToInt)
  36. .Case("sign-ext", HasSignExt)
  37. .Case("exception-handling", HasExceptionHandling)
  38. .Case("bulk-memory", HasBulkMemory)
  39. .Case("atomics", HasAtomics)
  40. .Case("mutable-globals", HasMutableGlobals)
  41. .Case("multivalue", HasMultivalue)
  42. .Case("tail-call", HasTailCall)
  43. .Default(false);
  44. }
  45. bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
  46. return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
  47. }
  48. void WebAssemblyTargetInfo::fillValidCPUList(
  49. SmallVectorImpl<StringRef> &Values) const {
  50. Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
  51. }
  52. void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
  53. MacroBuilder &Builder) const {
  54. defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
  55. if (SIMDLevel >= SIMD128)
  56. Builder.defineMacro("__wasm_simd128__");
  57. if (SIMDLevel >= UnimplementedSIMD128)
  58. Builder.defineMacro("__wasm_unimplemented_simd128__");
  59. if (HasNontrappingFPToInt)
  60. Builder.defineMacro("__wasm_nontrapping_fptoint__");
  61. if (HasSignExt)
  62. Builder.defineMacro("__wasm_sign_ext__");
  63. if (HasExceptionHandling)
  64. Builder.defineMacro("__wasm_exception_handling__");
  65. if (HasBulkMemory)
  66. Builder.defineMacro("__wasm_bulk_memory__");
  67. if (HasAtomics)
  68. Builder.defineMacro("__wasm_atomics__");
  69. if (HasMutableGlobals)
  70. Builder.defineMacro("__wasm_mutable_globals__");
  71. if (HasMultivalue)
  72. Builder.defineMacro("__wasm_multivalue__");
  73. if (HasTailCall)
  74. Builder.defineMacro("__wasm_tail_call__");
  75. }
  76. void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
  77. SIMDEnum Level) {
  78. switch (Level) {
  79. case UnimplementedSIMD128:
  80. Features["unimplemented-simd128"] = true;
  81. LLVM_FALLTHROUGH;
  82. case SIMD128:
  83. Features["simd128"] = true;
  84. LLVM_FALLTHROUGH;
  85. case NoSIMD:
  86. break;
  87. }
  88. }
  89. bool WebAssemblyTargetInfo::initFeatureMap(
  90. llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
  91. const std::vector<std::string> &FeaturesVec) const {
  92. if (CPU == "bleeding-edge") {
  93. Features["nontrapping-fptoint"] = true;
  94. Features["sign-ext"] = true;
  95. Features["atomics"] = true;
  96. Features["mutable-globals"] = true;
  97. setSIMDLevel(Features, SIMD128);
  98. }
  99. // Other targets do not consider user-configured features here, but while we
  100. // are actively developing new features it is useful to let user-configured
  101. // features control availability of builtins
  102. setSIMDLevel(Features, SIMDLevel);
  103. if (HasNontrappingFPToInt)
  104. Features["nontrapping-fptoint"] = true;
  105. if (HasSignExt)
  106. Features["sign-ext"] = true;
  107. if (HasExceptionHandling)
  108. Features["exception-handling"] = true;
  109. if (HasBulkMemory)
  110. Features["bulk-memory"] = true;
  111. if (HasAtomics)
  112. Features["atomics"] = true;
  113. if (HasMutableGlobals)
  114. Features["mutable-globals"] = true;
  115. if (HasMultivalue)
  116. Features["multivalue"] = true;
  117. if (HasTailCall)
  118. Features["tail-call"] = true;
  119. return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
  120. }
  121. bool WebAssemblyTargetInfo::handleTargetFeatures(
  122. std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
  123. for (const auto &Feature : Features) {
  124. if (Feature == "+simd128") {
  125. SIMDLevel = std::max(SIMDLevel, SIMD128);
  126. continue;
  127. }
  128. if (Feature == "-simd128") {
  129. SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
  130. continue;
  131. }
  132. if (Feature == "+unimplemented-simd128") {
  133. SIMDLevel = std::max(SIMDLevel, SIMDEnum(UnimplementedSIMD128));
  134. continue;
  135. }
  136. if (Feature == "-unimplemented-simd128") {
  137. SIMDLevel = std::min(SIMDLevel, SIMDEnum(UnimplementedSIMD128 - 1));
  138. continue;
  139. }
  140. if (Feature == "+nontrapping-fptoint") {
  141. HasNontrappingFPToInt = true;
  142. continue;
  143. }
  144. if (Feature == "-nontrapping-fptoint") {
  145. HasNontrappingFPToInt = false;
  146. continue;
  147. }
  148. if (Feature == "+sign-ext") {
  149. HasSignExt = true;
  150. continue;
  151. }
  152. if (Feature == "-sign-ext") {
  153. HasSignExt = false;
  154. continue;
  155. }
  156. if (Feature == "+exception-handling") {
  157. HasExceptionHandling = true;
  158. continue;
  159. }
  160. if (Feature == "-exception-handling") {
  161. HasExceptionHandling = false;
  162. continue;
  163. }
  164. if (Feature == "+bulk-memory") {
  165. HasBulkMemory = true;
  166. continue;
  167. }
  168. if (Feature == "-bulk-memory") {
  169. HasBulkMemory = false;
  170. continue;
  171. }
  172. if (Feature == "+atomics") {
  173. HasAtomics = true;
  174. continue;
  175. }
  176. if (Feature == "-atomics") {
  177. HasAtomics = false;
  178. continue;
  179. }
  180. if (Feature == "+mutable-globals") {
  181. HasMutableGlobals = true;
  182. continue;
  183. }
  184. if (Feature == "-mutable-globals") {
  185. HasMutableGlobals = false;
  186. continue;
  187. }
  188. if (Feature == "+multivalue") {
  189. HasMultivalue = true;
  190. continue;
  191. }
  192. if (Feature == "-multivalue") {
  193. HasMultivalue = false;
  194. continue;
  195. }
  196. if (Feature == "+tail-call") {
  197. HasTailCall = true;
  198. continue;
  199. }
  200. if (Feature == "-tail-call") {
  201. HasTailCall = false;
  202. continue;
  203. }
  204. Diags.Report(diag::err_opt_not_valid_with_opt)
  205. << Feature << "-target-feature";
  206. return false;
  207. }
  208. return true;
  209. }
  210. ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
  211. return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
  212. Builtin::FirstTSBuiltin);
  213. }
  214. void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
  215. MacroBuilder &Builder) const {
  216. WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
  217. defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
  218. }
  219. void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
  220. MacroBuilder &Builder) const {
  221. WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
  222. defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
  223. }