1 /* 2 * This software is licensed under the terms of the MIT License. 3 * See COPYING for further information. 4 * --- 5 * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>. 6 * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>. 7 */ 8 9 #ifndef IGUARD_util_compat_h 10 #define IGUARD_util_compat_h 11 12 #include "taisei.h" 13 14 // Common standard library headers 15 #include <complex.h> 16 #include <ctype.h> 17 #include <float.h> 18 #include <inttypes.h> 19 #include <limits.h> 20 #include <math.h> 21 #include <stdalign.h> 22 #include <stdbool.h> 23 #include <stddef.h> 24 #include <stdint.h> 25 #include <stdlib.h> 26 #include <stdnoreturn.h> 27 #include <string.h> 28 29 #include "util/assert.h" 30 31 #ifdef __FAST_MATH__ 32 #error -ffast-math is prohibited 33 #endif 34 35 #ifdef _WIN32 36 // Include the god-awful windows.h header here so that we can fight the obnoxious namespace pollution it introduces. 37 // We obviously don't need it in every source file, but it's easier to do it globally and early than to try to infer 38 // just where down the maze of includes some of our dependencies happens to smuggle it in. 39 // 40 // *sigh* 41 // 42 // Goddamn it. 43 44 // Make sure we get the "unicode" (actually UTF-16) versions of win32 APIs; it defaults to legacy crippled ones. 45 #ifndef UNICODE 46 #define UNICODE 47 #endif 48 #ifndef _UNICODE 49 #define _UNICODE 50 #endif 51 52 // Ask windows.h to include a little bit less of the stupid crap we'll never use. 53 // Some of it actually clashes with our names. 54 #define WIN32_LEAN_AND_MEAN 55 #define NOGDI 56 #define NOMINMAX 57 58 #include <windows.h> 59 60 // far/near pointers are obviously very relevant for modern CPUs and totally deserve their very own, unprefixed keywords! 61 #undef near 62 #undef far 63 #endif 64 65 // This macro should be provided by stddef.h, but in practice it sometimes is not. 66 #ifndef offsetof 67 #ifdef __GNUC__ 68 #define offsetof(type, field) __builtin_offsetof(type, field) 69 #else 70 #define offsetof(type, field) ((size_t)&(((type *)0)->field)) 71 #endif 72 #endif 73 74 #define PRAGMA(p) _Pragma(#p) 75 76 #ifndef __GNUC__ // clang defines this too 77 #define __attribute__(...) 78 #define __extension__ 79 #define UNREACHABLE 80 #define DIAGNOSTIC(x) 81 #define DIAGNOSTIC_GCC(x) 82 #define DIAGNOSTIC_CLANG(x) 83 #define LIKELY(x) (bool)(x) 84 #define UNLIKELY(x) (bool)(x) 85 #else 86 #ifdef TAISEI_BUILDCONF_USE_GNU_EXTENSIONS 87 #define USE_GNU_EXTENSIONS 88 #endif 89 #define UNREACHABLE __builtin_unreachable() 90 91 #define DIAGNOSTIC(x) PRAGMA(GCC diagnostic x) 92 93 #if defined(__clang__) 94 #define DIAGNOSTIC_GCC(x) 95 #define DIAGNOSTIC_CLANG(x) PRAGMA(clang diagnostic x) 96 #else 97 #define DIAGNOSTIC_GCC(x) PRAGMA(GCC diagnostic x) 98 #define DIAGNOSTIC_CLANG(x) 99 #endif 100 101 #define LIKELY(x) __builtin_expect((bool)(x), 1) 102 #define UNLIKELY(x) __builtin_expect((bool)(x), 0) 103 #endif 104 105 #ifndef __has_attribute 106 #ifdef __GNUC__ 107 #define __has_attribute(attr) 1 108 #else 109 #define __has_attribute(attr) 0 110 #endif 111 #endif 112 113 #undef ASSUME 114 115 #ifdef __has_builtin 116 #if __has_builtin(__builtin_assume) 117 #define ASSUME(x) __builtin_assume(x) 118 #endif 119 #endif 120 121 #if !defined(ASSUME) && defined(__GNUC__) 122 #define ASSUME(x) do { if(!(x)) { UNREACHABLE; } } while(0) 123 #endif 124 125 #ifndef ASSUME 126 #define ASSUME(x) 127 #endif 128 129 // On windows, use the MinGW implementations of printf and friends instead of the crippled mscrt ones. 130 #ifdef __USE_MINGW_ANSI_STDIO 131 #define FORMAT_ATTR __MINGW_PRINTF_FORMAT 132 #else 133 #define FORMAT_ATTR printf 134 #endif 135 136 #undef uint 137 typedef unsigned int uint; 138 139 #undef ushort 140 typedef unsigned short ushort; 141 142 #undef ulong 143 typedef unsigned long ulong; 144 145 #undef uchar 146 typedef unsigned char uchar; 147 148 #undef schar 149 typedef signed char schar; 150 151 #undef float32 152 typedef float float32; 153 154 #undef float64 155 typedef double float64; 156 157 #undef float64x 158 typedef long double float64x; 159 160 #undef real 161 typedef float64 real; 162 163 #undef cmplx32 164 typedef _Complex float cmplx32; 165 166 #undef cmplx64 167 typedef _Complex double cmplx64; 168 169 #undef cmplx 170 typedef cmplx64 cmplx; 171 172 // These definitions are common but non-standard, so we provide our own 173 #undef M_PI 174 #undef M_PI_2 175 #undef M_PI_4 176 #undef M_E 177 #define M_PI 3.14159265358979323846 178 #define M_PI_2 1.57079632679489661923 179 #define M_PI_4 0.78539816339744830962 180 #define M_E 2.7182818284590452354 181 182 #ifndef TAISEI_BUILDCONF_HAVE_MAX_ALIGN_T 183 #if TAISEI_BUILDCONF_MALLOC_ALIGNMENT <= 0 184 #warning malloc alignment is unknown, assuming 8 185 #undef TAISEI_BUILDCONF_MALLOC_ALIGNMENT 186 #define TAISEI_BUILDCONF_MALLOC_ALIGNMENT 8 187 #endif 188 189 #undef max_align_t 190 #define max_align_t _fake_max_align_t 191 typedef struct { alignas(TAISEI_BUILDCONF_MALLOC_ALIGNMENT) char a; } max_align_t; 192 #endif 193 194 // In case the C11 CMPLX macro is not present, try our best to provide a substitute 195 #if !defined CMPLX 196 #undef HAS_BUILTIN_COMPLEX 197 198 #if defined __has_builtin 199 #if __has_builtin(__builtin_complex) 200 #define HAS_BUILTIN_COMPLEX 201 #endif 202 #else 203 #if defined __GNUC__ && defined __GNUC_MINOR__ 204 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) 205 #define HAS_BUILTIN_COMPLEX 206 #endif 207 #endif 208 #endif 209 210 #if defined HAS_BUILTIN_COMPLEX 211 #define CMPLX(re,im) __builtin_complex((double)(re), (double)(im)) 212 #elif defined __clang__ 213 #define CMPLX(re,im) (__extension__ (_Complex double){(double)(re), (double)(im)}) 214 #elif defined _Imaginary_I 215 #define CMPLX(re,im) (_Complex double)((double)(re) + _Imaginary_I * (double)(im)) 216 #else 217 #define CMPLX(re,im) (_Complex double)((double)(re) + _Complex_I * (double)(im)) 218 #endif 219 #elif defined __EMSCRIPTEN__ && defined __clang__ 220 // CMPLX from emscripten headers uses the clang-specific syntax without __extension__ 221 #pragma clang diagnostic ignored "-Wcomplex-component-init" 222 #endif 223 224 /* 225 * Abstract away the nasty GNU attribute syntax. 226 */ 227 228 // Function is a hot spot. 229 #define attr_hot \ 230 __attribute__ ((hot)) 231 232 // Function has no side-effects. 233 #define attr_pure \ 234 __attribute__ ((pure)) 235 236 // Function has no side-effects, return value depends on arguments only. 237 // Must not take pointer parameters, must not return void. 238 #define attr_const \ 239 __attribute__ ((const)) 240 241 // Function never returns NULL. 242 #define attr_returns_nonnull \ 243 __attribute__ ((returns_nonnull)) 244 245 // Function must be called with NULL as the last argument (for varargs functions). 246 #define attr_sentinel \ 247 __attribute__ ((sentinel)) 248 249 // Symbol is meant to be possibly unused. 250 #define attr_unused \ 251 __attribute__ ((unused)) 252 253 // Symbol should be emitted even if it appears to be unused. 254 #define attr_used \ 255 __attribute__ ((used)) 256 257 // Function or type is deprecated and should not be used. 258 #define attr_deprecated(msg) \ 259 __attribute__ ((deprecated(msg))) 260 261 // Function parameters at specified positions must not be NULL. 262 #define attr_nonnull(...) \ 263 __attribute__ ((nonnull(__VA_ARGS__))) 264 265 // All pointer parameters must not be NULL. 266 #define attr_nonnull_all \ 267 __attribute__ ((nonnull)) 268 269 // The return value of this function must not be ignored. 270 #define attr_nodiscard \ 271 __attribute__ ((warn_unused_result)) 272 273 // Function takes a printf-style format string and variadic arguments. 274 #define attr_printf(fmt_index, firstarg_index) \ 275 __attribute__ ((format(FORMAT_ATTR, fmt_index, firstarg_index))) 276 277 // Function must be inlined regardless of optimization settings. 278 #define attr_must_inline \ 279 __attribute__ ((always_inline)) 280 281 // Function returns a pointer aligned to x bytes 282 #define attr_returns_aligned(x) \ 283 __attribute__ ((assume_aligned(x))) 284 285 // Function returns a pointer aligned the same as max_align_t 286 #define attr_returns_max_aligned \ 287 attr_returns_aligned(alignof(max_align_t)) 288 289 // Shorthand: always returns non-null pointer aligned to max_align_t; no discard. 290 #define attr_returns_allocated \ 291 attr_returns_nonnull attr_returns_max_aligned attr_nodiscard 292 293 // Structure must not be initialized with an implicit (non-designated) initializer. 294 #if __has_attribute(designated_init) && defined(TAISEI_BUILDCONF_USE_DESIGNATED_INIT) 295 #define attr_designated_init \ 296 __attribute__ ((designated_init)) 297 #else 298 #define attr_designated_init 299 #endif 300 301 #define INLINE static inline attr_must_inline __attribute__((gnu_inline)) 302 303 #ifdef USE_GNU_EXTENSIONS 304 #define ASSUME_ALIGNED(expr, alignment) (__extension__ ({ \ 305 static_assert(__builtin_constant_p(alignment), ""); \ 306 __auto_type _assume_aligned_ptr = (expr); \ 307 assert(((uintptr_t)_assume_aligned_ptr & ((alignment) - 1)) == 0); \ 308 __builtin_assume_aligned(_assume_aligned_ptr, (alignment)); \ 309 })) 310 #else 311 #define ASSUME_ALIGNED(expr, alignment) (expr) 312 #endif 313 314 #define CASTPTR_ASSUME_ALIGNED(expr, type) ((type*)ASSUME_ALIGNED((expr), alignof(type))) 315 316 #ifdef USE_GNU_EXTENSIONS 317 #define NOT_NULL(expr) (__extension__ ({ \ 318 __auto_type _assume_not_null_ptr = (expr); \ 319 assume(_assume_not_null_ptr != NULL); \ 320 _assume_not_null_ptr; \ 321 })) 322 #else 323 #define NOT_NULL(expr) (expr) 324 #endif 325 326 #ifdef __SWITCH__ 327 #include "../arch_switch.h" 328 #define atexit nxAtExit 329 #define exit nxExit 330 #define abort nxAbort 331 #endif 332 333 #endif // IGUARD_util_compat_h 334