detect_compiler_arch.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. // Copyright 2020 Google LLC
  2. // SPDX-License-Identifier: Apache-2.0
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #ifndef HIGHWAY_HWY_DETECT_COMPILER_ARCH_H_
  16. #define HIGHWAY_HWY_DETECT_COMPILER_ARCH_H_
  17. // Detects compiler and arch from predefined macros. Zero dependencies for
  18. // inclusion by foreach_target.h.
  19. // Add to #if conditions to prevent IDE from graying out code.
  20. #if (defined __CDT_PARSER__) || (defined __INTELLISENSE__) || \
  21. (defined Q_CREATOR_RUN) || (defined __CLANGD__) || \
  22. (defined GROK_ELLIPSIS_BUILD)
  23. #define HWY_IDE 1
  24. #else
  25. #define HWY_IDE 0
  26. #endif
  27. //------------------------------------------------------------------------------
  28. // Compiler
  29. // Actual MSVC, not clang-cl, which defines _MSC_VER but doesn't behave like
  30. // MSVC in other aspects (e.g. HWY_DIAGNOSTICS).
  31. #if defined(_MSC_VER) && !defined(__clang__)
  32. #define HWY_COMPILER_MSVC _MSC_VER
  33. #else
  34. #define HWY_COMPILER_MSVC 0
  35. #endif
  36. #if defined(_MSC_VER) && defined(__clang__)
  37. #define HWY_COMPILER_CLANGCL _MSC_VER
  38. #else
  39. #define HWY_COMPILER_CLANGCL 0
  40. #endif
  41. #ifdef __INTEL_COMPILER
  42. #define HWY_COMPILER_ICC __INTEL_COMPILER
  43. #else
  44. #define HWY_COMPILER_ICC 0
  45. #endif
  46. #ifdef __INTEL_LLVM_COMPILER
  47. #define HWY_COMPILER_ICX __INTEL_LLVM_COMPILER
  48. #else
  49. #define HWY_COMPILER_ICX 0
  50. #endif
  51. // HWY_COMPILER_GCC is a generic macro for all compilers implementing the GNU
  52. // compiler extensions (eg. Clang, Intel...)
  53. #ifdef __GNUC__
  54. #define HWY_COMPILER_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
  55. #else
  56. #define HWY_COMPILER_GCC 0
  57. #endif
  58. // Clang or clang-cl, not GCC.
  59. #ifdef __clang__
  60. // In case of Apple LLVM (whose version number is unrelated to that of LLVM) or
  61. // an invalid version number, deduce it from the presence of warnings.
  62. // Originally based on
  63. // https://github.com/simd-everywhere/simde/blob/47d6e603de9d04ee05cdfbc57cf282a02be1bf2a/simde/simde-detect-clang.h#L59.
  64. // Please send updates below to them as well, thanks!
  65. #if defined(__apple_build_version__) || __clang_major__ >= 999
  66. #if __has_warning("-Woverriding-option")
  67. #define HWY_COMPILER_CLANG 1801
  68. // No new warnings in 17.0, and Apple LLVM 15.3, which should be 1600, already
  69. // has the unsafe_buffer_usage attribute, so we instead check for new builtins.
  70. #elif __has_builtin(__builtin_nondeterministic_value)
  71. #define HWY_COMPILER_CLANG 1700
  72. #elif __has_attribute(nouwtable) // no new warnings in 16.0
  73. #define HWY_COMPILER_CLANG 1600
  74. #elif __has_warning("-Warray-parameter")
  75. #define HWY_COMPILER_CLANG 1500
  76. #elif __has_warning("-Wbitwise-instead-of-logical")
  77. #define HWY_COMPILER_CLANG 1400
  78. #elif __has_warning("-Wreserved-identifier")
  79. #define HWY_COMPILER_CLANG 1300
  80. #elif __has_warning("-Wformat-insufficient-args")
  81. #define HWY_COMPILER_CLANG 1200
  82. #elif __has_warning("-Wimplicit-const-int-float-conversion")
  83. #define HWY_COMPILER_CLANG 1100
  84. #elif __has_warning("-Wmisleading-indentation")
  85. #define HWY_COMPILER_CLANG 1000
  86. #elif defined(__FILE_NAME__)
  87. #define HWY_COMPILER_CLANG 900
  88. #elif __has_warning("-Wextra-semi-stmt") || \
  89. __has_builtin(__builtin_rotateleft32)
  90. #define HWY_COMPILER_CLANG 800
  91. // For reasons unknown, XCode 10.3 (Apple LLVM version 10.0.1) is apparently
  92. // based on Clang 7, but does not support the warning we test.
  93. // See https://en.wikipedia.org/wiki/Xcode#Toolchain_versions and
  94. // https://trac.macports.org/wiki/XcodeVersionInfo.
  95. #elif __has_warning("-Wc++98-compat-extra-semi") || \
  96. (defined(__apple_build_version__) && __apple_build_version__ >= 10010000)
  97. #define HWY_COMPILER_CLANG 700
  98. #else // Anything older than 7.0 is not recommended for Highway.
  99. #define HWY_COMPILER_CLANG 600
  100. #endif // __has_warning chain
  101. #define HWY_COMPILER3_CLANG (HWY_COMPILER_CLANG * 100)
  102. #else // use normal version
  103. #define HWY_COMPILER_CLANG (__clang_major__ * 100 + __clang_minor__)
  104. #define HWY_COMPILER3_CLANG \
  105. (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
  106. #endif
  107. #else // Not clang
  108. #define HWY_COMPILER_CLANG 0
  109. #define HWY_COMPILER3_CLANG 0
  110. #endif
  111. #if HWY_COMPILER_GCC && !HWY_COMPILER_CLANG && !HWY_COMPILER_ICC && \
  112. !HWY_COMPILER_ICX
  113. #define HWY_COMPILER_GCC_ACTUAL HWY_COMPILER_GCC
  114. #else
  115. #define HWY_COMPILER_GCC_ACTUAL 0
  116. #endif
  117. // More than one may be nonzero, but we want at least one.
  118. #if 0 == (HWY_COMPILER_MSVC + HWY_COMPILER_CLANGCL + HWY_COMPILER_ICC + \
  119. HWY_COMPILER_ICX + HWY_COMPILER_GCC + HWY_COMPILER_CLANG)
  120. #error "Unsupported compiler"
  121. #endif
  122. // We should only detect one of these (only clang/clangcl/icx overlap)
  123. #if 1 < (!!HWY_COMPILER_MSVC + (!!HWY_COMPILER_ICC & !HWY_COMPILER_ICX) + \
  124. !!HWY_COMPILER_GCC_ACTUAL + \
  125. !!(HWY_COMPILER_ICX | HWY_COMPILER_CLANGCL | HWY_COMPILER_CLANG))
  126. #error "Detected multiple compilers"
  127. #endif
  128. //------------------------------------------------------------------------------
  129. // Compiler features and C++ version
  130. #ifdef __has_builtin
  131. #define HWY_HAS_BUILTIN(name) __has_builtin(name)
  132. #else
  133. #define HWY_HAS_BUILTIN(name) 0
  134. #endif
  135. #ifdef __has_attribute
  136. #define HWY_HAS_ATTRIBUTE(name) __has_attribute(name)
  137. #else
  138. #define HWY_HAS_ATTRIBUTE(name) 0
  139. #endif
  140. #ifdef __has_cpp_attribute
  141. #define HWY_HAS_CPP_ATTRIBUTE(name) __has_cpp_attribute(name)
  142. #else
  143. #define HWY_HAS_CPP_ATTRIBUTE(name) 0
  144. #endif
  145. #ifdef __has_feature
  146. #define HWY_HAS_FEATURE(name) __has_feature(name)
  147. #else
  148. #define HWY_HAS_FEATURE(name) 0
  149. #endif
  150. // NOTE: clang ~17 does not correctly handle wrapping __has_include in a macro.
  151. #if HWY_COMPILER_MSVC && defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus
  152. #define HWY_CXX_LANG _MSVC_LANG
  153. #else
  154. #define HWY_CXX_LANG __cplusplus
  155. #endif
  156. #if defined(__cpp_constexpr) && __cpp_constexpr >= 201603L
  157. #define HWY_CXX17_CONSTEXPR constexpr
  158. #else
  159. #define HWY_CXX17_CONSTEXPR
  160. #endif
  161. #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304L
  162. #define HWY_CXX14_CONSTEXPR constexpr
  163. #else
  164. #define HWY_CXX14_CONSTEXPR
  165. #endif
  166. #if HWY_CXX_LANG >= 201703L
  167. #define HWY_IF_CONSTEXPR if constexpr
  168. #else
  169. #define HWY_IF_CONSTEXPR if
  170. #endif
  171. //------------------------------------------------------------------------------
  172. // Architecture
  173. #if defined(__i386__) || defined(_M_IX86)
  174. #define HWY_ARCH_X86_32 1
  175. #else
  176. #define HWY_ARCH_X86_32 0
  177. #endif
  178. #if defined(__x86_64__) || defined(_M_X64)
  179. #define HWY_ARCH_X86_64 1
  180. #else
  181. #define HWY_ARCH_X86_64 0
  182. #endif
  183. #if HWY_ARCH_X86_32 && HWY_ARCH_X86_64
  184. #error "Cannot have both x86-32 and x86-64"
  185. #endif
  186. #if HWY_ARCH_X86_32 || HWY_ARCH_X86_64
  187. #define HWY_ARCH_X86 1
  188. #else
  189. #define HWY_ARCH_X86 0
  190. #endif
  191. #if defined(__powerpc64__) || defined(_M_PPC) || defined(__powerpc__)
  192. #define HWY_ARCH_PPC 1
  193. #else
  194. #define HWY_ARCH_PPC 0
  195. #endif
  196. #if defined(__powerpc64__) || (HWY_ARCH_PPC && defined(__64BIT__))
  197. #define HWY_ARCH_PPC_64 1
  198. #else
  199. #define HWY_ARCH_PPC_64 0
  200. #endif
  201. // aarch32 is currently not supported; please raise an issue if you want it.
  202. #if defined(__ARM_ARCH_ISA_A64) || defined(__aarch64__) || defined(_M_ARM64)
  203. #define HWY_ARCH_ARM_A64 1
  204. #else
  205. #define HWY_ARCH_ARM_A64 0
  206. #endif
  207. #if (defined(__ARM_ARCH) && __ARM_ARCH == 7) || (defined(_M_ARM) && _M_ARM == 7)
  208. #define HWY_ARCH_ARM_V7 1
  209. #else
  210. #define HWY_ARCH_ARM_V7 0
  211. #endif
  212. #if HWY_ARCH_ARM_A64 && HWY_ARCH_ARM_V7
  213. #error "Cannot have both A64 and V7"
  214. #endif
  215. // Any *supported* version of Arm, i.e. 7 or later
  216. #if HWY_ARCH_ARM_A64 || HWY_ARCH_ARM_V7
  217. #define HWY_ARCH_ARM 1
  218. #else
  219. #define HWY_ARCH_ARM 0
  220. #endif
  221. // Older than Armv7 (e.g. armel aka Armv5) => we do not support SIMD.
  222. #if (defined(__arm__) || defined(_M_ARM)) && !HWY_ARCH_ARM
  223. #define HWY_ARCH_ARM_OLD 1
  224. #else
  225. #define HWY_ARCH_ARM_OLD 0
  226. #endif
  227. #if defined(__EMSCRIPTEN__) || defined(__wasm__) || defined(__WASM__)
  228. #define HWY_ARCH_WASM 1
  229. #else
  230. #define HWY_ARCH_WASM 0
  231. #endif
  232. #ifdef __riscv
  233. #define HWY_ARCH_RISCV 1
  234. #else
  235. #define HWY_ARCH_RISCV 0
  236. #endif
  237. // DEPRECATED names; please use HWY_ARCH_RISCV instead.
  238. #define HWY_ARCH_RVV HWY_ARCH_RISCV
  239. #if HWY_ARCH_RISCV && defined(__riscv_xlen)
  240. #if __riscv_xlen == 32
  241. #define HWY_ARCH_RISCV_32 1
  242. #else
  243. #define HWY_ARCH_RISCV_32 0
  244. #endif
  245. #if __riscv_xlen == 64
  246. #define HWY_ARCH_RISCV_64 1
  247. #else
  248. #define HWY_ARCH_RISCV_64 0
  249. #endif
  250. #else // !HWY_ARCH_RISCV || !defined(__riscv_xlen)
  251. #define HWY_ARCH_RISCV_32 0
  252. #define HWY_ARCH_RISCV_64 0
  253. #endif // HWY_ARCH_RISCV && defined(__riscv_xlen)
  254. #if HWY_ARCH_RISCV_32 && HWY_ARCH_RISCV_64
  255. #error "Cannot have both RISCV_32 and RISCV_64"
  256. #endif
  257. #if defined(__s390x__)
  258. #define HWY_ARCH_S390X 1
  259. #else
  260. #define HWY_ARCH_S390X 0
  261. #endif
  262. // It is an error to detect multiple architectures at the same time, but OK to
  263. // detect none of the above.
  264. #if (HWY_ARCH_X86 + HWY_ARCH_PPC + HWY_ARCH_ARM + HWY_ARCH_ARM_OLD + \
  265. HWY_ARCH_WASM + HWY_ARCH_RISCV + HWY_ARCH_S390X) > 1
  266. #error "Must not detect more than one architecture"
  267. #endif
  268. //------------------------------------------------------------------------------
  269. // Operating system
  270. #if defined(_WIN32) || defined(_WIN64)
  271. #define HWY_OS_WIN 1
  272. #else
  273. #define HWY_OS_WIN 0
  274. #endif
  275. #if defined(linux) || defined(__linux__)
  276. #define HWY_OS_LINUX 1
  277. #else
  278. #define HWY_OS_LINUX 0
  279. #endif
  280. // iOS or Mac
  281. #if defined(__APPLE__)
  282. #define HWY_OS_APPLE 1
  283. #else
  284. #define HWY_OS_APPLE 0
  285. #endif
  286. #if defined(__FreeBSD__)
  287. #define HWY_OS_FREEBSD 1
  288. #else
  289. #define HWY_OS_FREEBSD 0
  290. #endif
  291. // It is an error to detect multiple OSes at the same time, but OK to
  292. // detect none of the above.
  293. #if (HWY_OS_WIN + HWY_OS_LINUX + HWY_OS_APPLE + HWY_OS_FREEBSD) > 1
  294. #error "Must not detect more than one OS"
  295. #endif
  296. //------------------------------------------------------------------------------
  297. // Endianness
  298. #if HWY_COMPILER_MSVC
  299. #if HWY_ARCH_PPC && defined(_XBOX_VER) && _XBOX_VER >= 200
  300. // XBox 360 is big-endian
  301. #define HWY_IS_LITTLE_ENDIAN 0
  302. #define HWY_IS_BIG_ENDIAN 1
  303. #else
  304. // All other targets supported by MSVC are little-endian
  305. #define HWY_IS_LITTLE_ENDIAN 1
  306. #define HWY_IS_BIG_ENDIAN 0
  307. #endif // HWY_ARCH_PPC && defined(_XBOX_VER) && _XBOX_VER >= 200
  308. #elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
  309. __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  310. #define HWY_IS_LITTLE_ENDIAN 1
  311. #define HWY_IS_BIG_ENDIAN 0
  312. #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
  313. __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  314. #define HWY_IS_LITTLE_ENDIAN 0
  315. #define HWY_IS_BIG_ENDIAN 1
  316. #else
  317. #error "Unable to detect endianness or unsupported byte order"
  318. #endif
  319. #if (HWY_IS_LITTLE_ENDIAN + HWY_IS_BIG_ENDIAN) != 1
  320. #error "Must only detect one byte order"
  321. #endif
  322. #endif // HIGHWAY_HWY_DETECT_COMPILER_ARCH_H_