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