compiler_specific.h (4815B)
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 <stdint.h> 12 #include <sys/types.h> 13 14 #include "lib/jxl/base/sanitizer_definitions.h" 15 16 // #if is shorter and safer than #ifdef. *_VERSION are zero if not detected, 17 // otherwise 100 * major + minor version. Note that other packages check for 18 // #ifdef COMPILER_MSVC, so we cannot use that same name. 19 20 #ifdef _MSC_VER 21 #define JXL_COMPILER_MSVC _MSC_VER 22 #else 23 #define JXL_COMPILER_MSVC 0 24 #endif 25 26 #ifdef __GNUC__ 27 #define JXL_COMPILER_GCC (__GNUC__ * 100 + __GNUC_MINOR__) 28 #else 29 #define JXL_COMPILER_GCC 0 30 #endif 31 32 #ifdef __clang__ 33 #define JXL_COMPILER_CLANG (__clang_major__ * 100 + __clang_minor__) 34 // Clang pretends to be GCC for compatibility. 35 #undef JXL_COMPILER_GCC 36 #define JXL_COMPILER_GCC 0 37 #else 38 #define JXL_COMPILER_CLANG 0 39 #endif 40 41 #if JXL_COMPILER_MSVC 42 #define JXL_RESTRICT __restrict 43 #elif JXL_COMPILER_GCC || JXL_COMPILER_CLANG 44 #define JXL_RESTRICT __restrict__ 45 #else 46 #define JXL_RESTRICT 47 #endif 48 49 #if JXL_COMPILER_MSVC 50 #define JXL_INLINE __forceinline 51 #define JXL_NOINLINE __declspec(noinline) 52 #else 53 #define JXL_INLINE inline __attribute__((always_inline)) 54 #define JXL_NOINLINE __attribute__((noinline)) 55 #endif 56 57 #if JXL_COMPILER_MSVC 58 #define JXL_NORETURN __declspec(noreturn) 59 #elif JXL_COMPILER_GCC || JXL_COMPILER_CLANG 60 #define JXL_NORETURN __attribute__((noreturn)) 61 #else 62 #define JXL_NORETURN 63 #endif 64 65 #if JXL_COMPILER_MSVC 66 #define JXL_UNREACHABLE_BUILTIN __assume(false) 67 #elif JXL_COMPILER_CLANG || JXL_COMPILER_GCC >= 405 68 #define JXL_UNREACHABLE_BUILTIN __builtin_unreachable() 69 #else 70 #define JXL_UNREACHABLE_BUILTIN 71 #endif 72 73 #if JXL_COMPILER_MSVC 74 #define JXL_MAYBE_UNUSED 75 #else 76 // Encountered "attribute list cannot appear here" when using the C++17 77 // [[maybe_unused]], so only use the old style attribute for now. 78 #define JXL_MAYBE_UNUSED __attribute__((unused)) 79 #endif 80 81 // MSAN execution won't hurt if some code it not inlined, but this can greatly 82 // improve compilation time. Unfortunately this macro can not be used just 83 // everywhere - inside header files it leads to "multiple definition" error; 84 // though it would be better not to have JXL_INLINE in header overall. 85 #if JXL_MEMORY_SANITIZER || JXL_ADDRESS_SANITIZER || JXL_THREAD_SANITIZER 86 #define JXL_MAYBE_INLINE JXL_MAYBE_UNUSED 87 #else 88 #define JXL_MAYBE_INLINE JXL_INLINE 89 #endif 90 91 #if JXL_COMPILER_MSVC 92 // Unsupported, __assume is not the same. 93 #define JXL_LIKELY(expr) expr 94 #define JXL_UNLIKELY(expr) expr 95 #else 96 #define JXL_LIKELY(expr) __builtin_expect(!!(expr), 1) 97 #define JXL_UNLIKELY(expr) __builtin_expect(!!(expr), 0) 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 #if JXL_COMPILER_MSVC 154 using ssize_t = intptr_t; 155 #endif 156 157 #endif // LIB_JXL_BASE_COMPILER_SPECIFIC_H_