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