compiler_specific.h (6602B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #ifndef LIB_JXL_BASE_COMPILER_SPECIFIC_H_ 7 #define LIB_JXL_BASE_COMPILER_SPECIFIC_H_ 8 9 // Macros for compiler version + nonstandard keywords, e.g. __builtin_expect. 10 11 #include <sys/types.h> 12 13 #include "lib/jxl/base/sanitizer_definitions.h" 14 15 #if JXL_ADDRESS_SANITIZER || JXL_MEMORY_SANITIZER || JXL_THREAD_SANITIZER 16 #include "sanitizer/common_interface_defs.h" // __sanitizer_print_stack_trace 17 #endif // defined(*_SANITIZER) 18 19 // #if is shorter and safer than #ifdef. *_VERSION are zero if not detected, 20 // otherwise 100 * major + minor version. Note that other packages check for 21 // #ifdef COMPILER_MSVC, so we cannot use that same name. 22 23 #ifdef _MSC_VER 24 #define JXL_COMPILER_MSVC _MSC_VER 25 #else 26 #define JXL_COMPILER_MSVC 0 27 #endif 28 29 #ifdef __GNUC__ 30 #define JXL_COMPILER_GCC (__GNUC__ * 100 + __GNUC_MINOR__) 31 #else 32 #define JXL_COMPILER_GCC 0 33 #endif 34 35 #ifdef __clang__ 36 #define JXL_COMPILER_CLANG (__clang_major__ * 100 + __clang_minor__) 37 // Clang pretends to be GCC for compatibility. 38 #undef JXL_COMPILER_GCC 39 #define JXL_COMPILER_GCC 0 40 #else 41 #define JXL_COMPILER_CLANG 0 42 #endif 43 44 #if JXL_COMPILER_MSVC 45 #define JXL_RESTRICT __restrict 46 #elif JXL_COMPILER_GCC || JXL_COMPILER_CLANG 47 #define JXL_RESTRICT __restrict__ 48 #else 49 #define JXL_RESTRICT 50 #endif 51 52 #if JXL_COMPILER_MSVC 53 #define JXL_INLINE __forceinline 54 #define JXL_NOINLINE __declspec(noinline) 55 #else 56 #define JXL_INLINE inline __attribute__((always_inline)) 57 #define JXL_NOINLINE __attribute__((noinline)) 58 #endif 59 60 #if JXL_COMPILER_MSVC 61 #define JXL_NORETURN __declspec(noreturn) 62 #elif JXL_COMPILER_GCC || JXL_COMPILER_CLANG 63 #define JXL_NORETURN __attribute__((noreturn)) 64 #else 65 #define JXL_NORETURN 66 #endif 67 68 #if JXL_COMPILER_MSVC 69 #define JXL_MAYBE_UNUSED 70 #else 71 // Encountered "attribute list cannot appear here" when using the C++17 72 // [[maybe_unused]], so only use the old style attribute for now. 73 #define JXL_MAYBE_UNUSED __attribute__((unused)) 74 #endif 75 76 // MSAN execution won't hurt if some code it not inlined, but this can greatly 77 // improve compilation time. Unfortunately this macro can not be used just 78 // everywhere - inside header files it leads to "multiple definition" error; 79 // though it would be better not to have JXL_INLINE in header overall. 80 #if JXL_MEMORY_SANITIZER || JXL_ADDRESS_SANITIZER || JXL_THREAD_SANITIZER 81 #define JXL_MAYBE_INLINE JXL_MAYBE_UNUSED 82 #else 83 #define JXL_MAYBE_INLINE JXL_INLINE 84 #endif 85 86 #if JXL_COMPILER_MSVC 87 // Unsupported, __assume is not the same. 88 #define JXL_LIKELY(expr) expr 89 #define JXL_UNLIKELY(expr) expr 90 #else 91 #define JXL_LIKELY(expr) __builtin_expect(!!(expr), 1) 92 #define JXL_UNLIKELY(expr) __builtin_expect(!!(expr), 0) 93 #endif 94 95 #if JXL_COMPILER_MSVC 96 #include <stdint.h> 97 using ssize_t = intptr_t; 98 #endif 99 100 // Returns a void* pointer which the compiler then assumes is N-byte aligned. 101 // Example: float* JXL_RESTRICT aligned = (float*)JXL_ASSUME_ALIGNED(in, 32); 102 // 103 // The assignment semantics are required by GCC/Clang. ICC provides an in-place 104 // __assume_aligned, whereas MSVC's __assume appears unsuitable. 105 #if JXL_COMPILER_CLANG 106 // Early versions of Clang did not support __builtin_assume_aligned. 107 #define JXL_HAS_ASSUME_ALIGNED __has_builtin(__builtin_assume_aligned) 108 #elif JXL_COMPILER_GCC 109 #define JXL_HAS_ASSUME_ALIGNED 1 110 #else 111 #define JXL_HAS_ASSUME_ALIGNED 0 112 #endif 113 114 #if JXL_HAS_ASSUME_ALIGNED 115 #define JXL_ASSUME_ALIGNED(ptr, align) __builtin_assume_aligned((ptr), (align)) 116 #else 117 #define JXL_ASSUME_ALIGNED(ptr, align) (ptr) /* not supported */ 118 #endif 119 120 #ifdef __has_attribute 121 #define JXL_HAVE_ATTRIBUTE(x) __has_attribute(x) 122 #else 123 #define JXL_HAVE_ATTRIBUTE(x) 0 124 #endif 125 126 // Raises warnings if the function return value is unused. Should appear as the 127 // first part of a function definition/declaration. 128 #if JXL_HAVE_ATTRIBUTE(nodiscard) 129 #define JXL_MUST_USE_RESULT [[nodiscard]] 130 #elif JXL_COMPILER_CLANG && JXL_HAVE_ATTRIBUTE(warn_unused_result) 131 #define JXL_MUST_USE_RESULT __attribute__((warn_unused_result)) 132 #else 133 #define JXL_MUST_USE_RESULT 134 #endif 135 136 // Disable certain -fsanitize flags for functions that are expected to include 137 // things like unsigned integer overflow. For example use in the function 138 // declaration JXL_NO_SANITIZE("unsigned-integer-overflow") to silence unsigned 139 // integer overflow ubsan messages. 140 #if JXL_COMPILER_CLANG && JXL_HAVE_ATTRIBUTE(no_sanitize) 141 #define JXL_NO_SANITIZE(X) __attribute__((no_sanitize(X))) 142 #else 143 #define JXL_NO_SANITIZE(X) 144 #endif 145 146 #if JXL_HAVE_ATTRIBUTE(__format__) 147 #define JXL_FORMAT(idx_fmt, idx_arg) \ 148 __attribute__((__format__(__printf__, idx_fmt, idx_arg))) 149 #else 150 #define JXL_FORMAT(idx_fmt, idx_arg) 151 #endif 152 153 // C++ standard. 154 #if defined(_MSC_VER) && !defined(__clang__) && defined(_MSVC_LANG) && \ 155 _MSVC_LANG > __cplusplus 156 #define JXL_CXX_LANG _MSVC_LANG 157 #else 158 #define JXL_CXX_LANG __cplusplus 159 #endif 160 161 // Known / distinguished C++ standards. 162 #define JXL_CXX_17 201703 163 164 // In most cases we consider build as "debug". Use `NDEBUG` for release build. 165 #if defined(JXL_IS_DEBUG_BUILD) 166 #undef JXL_IS_DEBUG_BUILD 167 #define JXL_IS_DEBUG_BUILD 1 168 #elif defined(NDEBUG) 169 #define JXL_IS_DEBUG_BUILD 0 170 #else 171 #define JXL_IS_DEBUG_BUILD 1 172 #endif 173 174 #if defined(JXL_CRASH_ON_ERROR) 175 #undef JXL_CRASH_ON_ERROR 176 #define JXL_CRASH_ON_ERROR 1 177 #else 178 #define JXL_CRASH_ON_ERROR 0 179 #endif 180 181 #if JXL_CRASH_ON_ERROR && !JXL_IS_DEBUG_BUILD 182 #error "JXL_CRASH_ON_ERROR requires JXL_IS_DEBUG_BUILD" 183 #endif 184 185 // Pass -DJXL_DEBUG_ON_ALL_ERROR at compile time to print debug messages on 186 // all error (fatal and non-fatal) status. 187 #if defined(JXL_DEBUG_ON_ALL_ERROR) 188 #undef JXL_DEBUG_ON_ALL_ERROR 189 #define JXL_DEBUG_ON_ALL_ERROR 1 190 #else 191 #define JXL_DEBUG_ON_ALL_ERROR 0 192 #endif 193 194 #if JXL_DEBUG_ON_ALL_ERROR && !JXL_IS_DEBUG_BUILD 195 #error "JXL_DEBUG_ON_ALL_ERROR requires JXL_IS_DEBUG_BUILD" 196 #endif 197 198 // Pass -DJXL_DEBUG_ON_ABORT={0} to disable the debug messages on 199 // (debug) JXL_ENSURE and JXL_DASSERT. 200 #if !defined(JXL_DEBUG_ON_ABORT) 201 #define JXL_DEBUG_ON_ABORT JXL_IS_DEBUG_BUILD 202 #endif // JXL_DEBUG_ON_ABORT 203 204 #if JXL_DEBUG_ON_ABORT && !JXL_IS_DEBUG_BUILD 205 #error "JXL_DEBUG_ON_ABORT requires JXL_IS_DEBUG_BUILD" 206 #endif 207 208 #if JXL_ADDRESS_SANITIZER || JXL_MEMORY_SANITIZER || JXL_THREAD_SANITIZER 209 #define JXL_PRINT_STACK_TRACE() __sanitizer_print_stack_trace(); 210 #else 211 #define JXL_PRINT_STACK_TRACE() 212 #endif 213 214 #if JXL_COMPILER_MSVC 215 #define JXL_CRASH() __debugbreak(), (void)abort() 216 #else 217 #define JXL_CRASH() (void)__builtin_trap() 218 #endif 219 220 #endif // LIB_JXL_BASE_COMPILER_SPECIFIC_H_