1 /*
2  * Copyright (C) 2015 The Android Open Source Project
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 
17 #ifndef TNT_UTILS_COMPILER_H
18 #define TNT_UTILS_COMPILER_H
19 
20 // compatibility with non-clang compilers...
21 #ifndef __has_attribute
22 #define __has_attribute(x) 0
23 #endif
24 
25 #ifndef __has_feature
26 #define __has_feature(x) 0
27 #endif
28 
29 #ifndef __has_builtin
30 #define __has_builtin(x) 0
31 #endif
32 
33 #if __has_attribute(visibility)
34 #    define UTILS_PUBLIC  __attribute__((visibility("default")))
35 #else
36 #    define UTILS_PUBLIC
37 #endif
38 
39 #if __has_attribute(deprecated)
40 #   define UTILS_DEPRECATED [[deprecated]]
41 #else
42 #   define UTILS_DEPRECATED
43 #endif
44 
45 #if __has_attribute(packed)
46 #   define UTILS_PACKED __attribute__((packed))
47 #else
48 #   define UTILS_PACKED
49 #endif
50 
51 #if __has_attribute(noreturn)
52 #    define UTILS_NORETURN __attribute__((noreturn))
53 #else
54 #    define UTILS_NORETURN
55 #endif
56 
57 #if __has_attribute(fallthrough)
58 #   define UTILS_FALLTHROUGH [[fallthrough]]
59 #else
60 #   define UTILS_FALLTHROUGH
61 #endif
62 
63 #if __has_attribute(visibility)
64 #    ifndef TNT_DEV
65 #        define UTILS_PRIVATE __attribute__((visibility("hidden")))
66 #    else
67 #        define UTILS_PRIVATE
68 #    endif
69 #else
70 #    define UTILS_PRIVATE
71 #endif
72 
73 #define UTILS_NO_SANITIZE_THREAD
74 #if __has_feature(thread_sanitizer)
75 #undef UTILS_NO_SANITIZE_THREAD
76 #define UTILS_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
77 #endif
78 
79 #define UTILS_HAS_SANITIZE_THREAD 0
80 #if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
81 #undef UTILS_HAS_SANITIZE_THREAD
82 #define UTILS_HAS_SANITIZE_THREAD 1
83 #endif
84 
85 #define UTILS_HAS_SANITIZE_MEMORY 0
86 #if __has_feature(memory_sanitizer)
87 #undef UTILS_HAS_SANITIZE_MEMORY
88 #define UTILS_HAS_SANITIZE_MEMORY 1
89 #endif
90 
91 /*
92  * helps the compiler's optimizer predicting branches
93  */
94 #if __has_builtin(__builtin_expect)
95 #   ifdef __cplusplus
96 #      define UTILS_LIKELY( exp )    (__builtin_expect( !!(exp), true ))
97 #      define UTILS_UNLIKELY( exp )  (__builtin_expect( !!(exp), false ))
98 #   else
99 #      define UTILS_LIKELY( exp )    (__builtin_expect( !!(exp), 1 ))
100 #      define UTILS_UNLIKELY( exp )  (__builtin_expect( !!(exp), 0 ))
101 #   endif
102 #else
103 #   define UTILS_LIKELY( exp )    (!!(exp))
104 #   define UTILS_UNLIKELY( exp )  (!!(exp))
105 #endif
106 
107 #if __has_builtin(__builtin_prefetch)
108 #   define UTILS_PREFETCH( exp ) (__builtin_prefetch(exp))
109 #else
110 #   define UTILS_PREFETCH( exp )
111 #endif
112 
113 #if __has_builtin(__builtin_assume)
114 #   define UTILS_ASSUME( exp ) (__builtin_assume(exp))
115 #else
116 #   define UTILS_ASSUME( exp )
117 #endif
118 
119 #if (defined(__i386__) || defined(__x86_64__))
120 #   define UTILS_HAS_HYPER_THREADING 1      // on x86 we assume we have hyper-threading.
121 #else
122 #   define UTILS_HAS_HYPER_THREADING 0
123 #endif
124 
125 #if defined(FILAMENT_SINGLE_THREADED)
126 #   define UTILS_HAS_THREADING 0
127 #elif defined(__EMSCRIPTEN__)
128 #   if defined(__EMSCRIPTEN_PTHREADS__) && defined(FILAMENT_WASM_THREADS)
129 #      define UTILS_HAS_THREADING 1
130 #   else
131 #      define UTILS_HAS_THREADING 0
132 #   endif
133 #else
134 #   define UTILS_HAS_THREADING 1
135 #endif
136 
137 #if __has_attribute(noinline)
138 #define UTILS_NOINLINE __attribute__((noinline))
139 #else
140 #define UTILS_NOINLINE
141 #endif
142 
143 #if __has_attribute(always_inline)
144 #define UTILS_ALWAYS_INLINE __attribute__((always_inline))
145 #else
146 #define UTILS_ALWAYS_INLINE
147 #endif
148 
149 #if __has_attribute(pure)
150 #define UTILS_PURE __attribute__((pure))
151 #else
152 #define UTILS_PURE
153 #endif
154 
155 #if __has_attribute(maybe_unused) || (defined(_MSC_VER) && _MSC_VER >= 1911)
156 #define UTILS_UNUSED [[maybe_unused]]
157 #define UTILS_UNUSED_IN_RELEASE [[maybe_unused]]
158 #elif __has_attribute(unused)
159 #define UTILS_UNUSED __attribute__((unused))
160 #define UTILS_UNUSED_IN_RELEASE __attribute__((unused))
161 #else
162 #define UTILS_UNUSED
163 #define UTILS_UNUSED_IN_RELEASE
164 #endif
165 
166 #if defined(_MSC_VER) && _MSC_VER >= 1900
167 #    define UTILS_RESTRICT __restrict
168 #elif (defined(__clang__) || defined(__GNUC__))
169 #    define UTILS_RESTRICT __restrict__
170 #else
171 #    define UTILS_RESTRICT
172 #endif
173 
174 #if defined(_MSC_VER) && _MSC_VER >= 1900
175 #   define UTILS_HAS_FEATURE_CXX_THREAD_LOCAL 1
176 #elif __has_feature(cxx_thread_local)
177 #   define UTILS_HAS_FEATURE_CXX_THREAD_LOCAL 1
178 #else
179 #   define UTILS_HAS_FEATURE_CXX_THREAD_LOCAL 0
180 #endif
181 
182 #if defined(_MSC_VER)
183 // MSVC does not support loop unrolling hints
184 #   define UTILS_UNROLL
185 #   define UTILS_NOUNROLL
186 #else
187 // C++11 allows pragmas to be specified as part of defines using the _Pragma syntax.
188 #   define UTILS_UNROLL _Pragma("unroll")
189 #   define UTILS_NOUNROLL _Pragma("nounroll")
190 #endif
191 
192 #if __has_feature(cxx_rtti) || defined(_CPPRTTI)
193 #   define UTILS_HAS_RTTI 1
194 #else
195 #   define UTILS_HAS_RTTI 0
196 #endif
197 
198 #ifdef __ARM_ACLE
199 #   include <arm_acle.h>
200 #   define UTILS_WAIT_FOR_INTERRUPT()   __wfi()
201 #   define UTILS_WAIT_FOR_EVENT()       __wfe()
202 #   define UTILS_BROADCAST_EVENT()      __sev()
203 #   define UTILS_SIGNAL_EVENT()         __sevl()
204 #   define UTILS_PAUSE()                __yield()
205 #   define UTILS_PREFETCHW(addr)        __pldx(1, 0, 0, addr)
206 #else // !__ARM_ACLE
207 #   if (defined(__i386__) || defined(__x86_64__))
208 #       define UTILS_X86_PAUSE              {__asm__ __volatile__( "rep; nop" : : : "memory" );}
209 #       define UTILS_WAIT_FOR_INTERRUPT()   UTILS_X86_PAUSE
210 #       define UTILS_WAIT_FOR_EVENT()       UTILS_X86_PAUSE
211 #       define UTILS_BROADCAST_EVENT()
212 #       define UTILS_SIGNAL_EVENT()
213 #       define UTILS_PAUSE()                UTILS_X86_PAUSE
214 #       define UTILS_PREFETCHW(addr)        UTILS_PREFETCH(addr)
215 #   else // !x86
216 #       define UTILS_WAIT_FOR_INTERRUPT()
217 #       define UTILS_WAIT_FOR_EVENT()
218 #       define UTILS_BROADCAST_EVENT()
219 #       define UTILS_SIGNAL_EVENT()
220 #       define UTILS_PAUSE()
221 #       define UTILS_PREFETCHW(addr)        UTILS_PREFETCH(addr)
222 #   endif // x86
223 #endif // __ARM_ACLE
224 
225 
226 // ssize_t is a POSIX type.
227 #if defined(WIN32) || defined(_WIN32)
228 #include <Basetsd.h>
229 typedef SSIZE_T ssize_t;
230 #endif
231 
232 #ifdef _MSC_VER
233 #   define UTILS_EMPTY_BASES __declspec(empty_bases)
234 #else
235 #   define UTILS_EMPTY_BASES
236 #endif
237 
238 #if defined(WIN32) || defined(_WIN32)
239 #define IMPORTSYMB __declspec(dllimport)
240 #else
241 #define IMPORTSYMB
242 #endif
243 
244 #if defined(_MSC_VER) && !defined(__PRETTY_FUNCTION__)
245 #    define __PRETTY_FUNCTION__ __FUNCSIG__
246 #endif
247 
248 
249 #if defined(_MSC_VER)
250 #   define UTILS_WARNING_PUSH _Pragma("warning( push )")
251 #   define UTILS_WARNING_POP _Pragma("warning( pop )")
252 #   define UTILS_WARNING_ENABLE_PADDED _Pragma("warning(1: 4324)")
253 #elif defined(__clang__)
254 #   define UTILS_WARNING_PUSH _Pragma("clang diagnostic push")
255 #   define UTILS_WARNING_POP  _Pragma("clang diagnostic pop")
256 #   define UTILS_WARNING_ENABLE_PADDED _Pragma("clang diagnostic warning \"-Wpadded\"")
257 #else
258 #   define UTILS_WARNING_PUSH
259 #   define UTILS_WARNING_POP
260 #   define UTILS_WARNING_ENABLE_PADDED
261 #endif
262 
263 #endif // TNT_UTILS_COMPILER_H
264