1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27 /** 28 * \file compiler.h 29 * Compiler-related stuff. 30 */ 31 32 33 #ifndef COMPILER_H 34 #define COMPILER_H 35 36 37 #include <assert.h> 38 #include <ctype.h> 39 #if defined(__alpha__) && defined(CCPML) 40 #include <cpml.h> /* use Compaq's Fast Math Library on Alpha */ 41 #else 42 #include <math.h> 43 #endif 44 #include <limits.h> 45 #include <stdlib.h> 46 #include <stdio.h> 47 #include <string.h> 48 #include <float.h> 49 #include <stdarg.h> 50 51 #include "c99_compat.h" /* inline, __func__, etc. */ 52 53 54 #ifdef __cplusplus 55 extern "C" { 56 #endif 57 58 59 /** 60 * Get standard integer types 61 */ 62 #include <stdint.h> 63 64 65 /** 66 * Sun compilers define __i386 instead of the gcc-style __i386__ 67 */ 68 #ifdef __SUNPRO_C 69 # if !defined(__i386__) && defined(__i386) 70 # define __i386__ 71 # elif !defined(__amd64__) && defined(__amd64) 72 # define __amd64__ 73 # elif !defined(__sparc__) && defined(__sparc) 74 # define __sparc__ 75 # endif 76 # if !defined(__volatile) 77 # define __volatile volatile 78 # endif 79 #endif 80 81 82 /** 83 * finite macro. 84 */ 85 #if defined(_MSC_VER) 86 # define finite _finite 87 #elif defined(__WATCOMC__) 88 # define finite _finite 89 #endif 90 91 92 /** 93 * Disable assorted warnings 94 */ 95 #if !defined(OPENSTEP) && (defined(_WIN32) && !defined(__CYGWIN__)) && !defined(BUILD_FOR_SNAP) 96 # if !defined(__GNUC__) /* mingw environment */ 97 # pragma warning( disable : 4068 ) /* unknown pragma */ 98 # pragma warning( disable : 4710 ) /* function 'foo' not inlined */ 99 # pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */ 100 # pragma warning( disable : 4127 ) /* conditional expression is constant */ 101 # if defined(MESA_MINWARN) 102 # pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */ 103 # pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */ 104 # pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */ 105 # pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */ 106 # pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */ 107 # endif 108 # endif 109 #endif 110 #if defined(__WATCOMC__) 111 # pragma disable_message(201) /* Disable unreachable code warnings */ 112 #endif 113 114 115 116 /* XXX: Use standard `inline` keyword instead */ 117 #ifndef INLINE 118 # define INLINE inline 119 #endif 120 121 122 /** 123 * PUBLIC/USED macros 124 * 125 * If we build the library with gcc's -fvisibility=hidden flag, we'll 126 * use the PUBLIC macro to mark functions that are to be exported. 127 * 128 * We also need to define a USED attribute, so the optimizer doesn't 129 * inline a static function that we later use in an alias. - ajax 130 */ 131 #ifndef PUBLIC 132 # if (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 133 # define PUBLIC __attribute__((visibility("default"))) 134 # define USED __attribute__((used)) 135 # else 136 # define PUBLIC 137 # define USED 138 # endif 139 #endif 140 141 142 /** 143 * __builtin_expect macros 144 */ 145 #if !defined(__GNUC__) 146 # define __builtin_expect(x, y) (x) 147 #endif 148 149 #ifndef likely 150 # ifdef __GNUC__ 151 # define likely(x) __builtin_expect(!!(x), 1) 152 # define unlikely(x) __builtin_expect(!!(x), 0) 153 # else 154 # define likely(x) (x) 155 # define unlikely(x) (x) 156 # endif 157 #endif 158 159 /* XXX: Use standard `__func__` instead */ 160 #ifndef __FUNCTION__ 161 # define __FUNCTION__ __func__ 162 #endif 163 164 /** 165 * Either define MESA_BIG_ENDIAN or MESA_LITTLE_ENDIAN, and CPU_TO_LE32. 166 * Do not use these unless absolutely necessary! 167 * Try to use a runtime test instead. 168 * For now, only used by some DRI hardware drivers for color/texel packing. 169 */ 170 #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN 171 #if defined(__linux__) 172 #include <byteswap.h> 173 #define CPU_TO_LE32( x ) bswap_32( x ) 174 #elif defined(__APPLE__) 175 #include <CoreFoundation/CFByteOrder.h> 176 #define CPU_TO_LE32( x ) CFSwapInt32HostToLittle( x ) 177 #elif (defined(_AIX) || defined(__blrts)) 178 static INLINE GLuint CPU_TO_LE32(GLuint x) 179 { 180 return (((x & 0x000000ff) << 24) | 181 ((x & 0x0000ff00) << 8) | 182 ((x & 0x00ff0000) >> 8) | 183 ((x & 0xff000000) >> 24)); 184 } 185 #elif defined(__OpenBSD__) 186 #include <sys/types.h> 187 #define CPU_TO_LE32( x ) htole32( x ) 188 #else /*__linux__ */ 189 #include <sys/endian.h> 190 #define CPU_TO_LE32( x ) bswap32( x ) 191 #endif /*__linux__*/ 192 #define MESA_BIG_ENDIAN 1 193 #else 194 #define CPU_TO_LE32( x ) ( x ) 195 #define MESA_LITTLE_ENDIAN 1 196 #endif 197 #define LE32_TO_CPU( x ) CPU_TO_LE32( x ) 198 199 200 201 #if !defined(CAPI) && defined(_WIN32) && !defined(BUILD_FOR_SNAP) 202 #define CAPI _cdecl 203 #endif 204 205 206 /** 207 * Create a macro so that asm functions can be linked into compilers other 208 * than GNU C 209 */ 210 #ifndef _ASMAPI 211 #if defined(_WIN32) && !defined(BUILD_FOR_SNAP)/* was: !defined( __GNUC__ ) && !defined( VMS ) && !defined( __INTEL_COMPILER )*/ 212 #define _ASMAPI __cdecl 213 #else 214 #define _ASMAPI 215 #endif 216 #ifdef PTR_DECL_IN_FRONT 217 #define _ASMAPIP * _ASMAPI 218 #else 219 #define _ASMAPIP _ASMAPI * 220 #endif 221 #endif 222 223 #ifdef USE_X86_ASM 224 #define _NORMAPI _ASMAPI 225 #define _NORMAPIP _ASMAPIP 226 #else 227 #define _NORMAPI 228 #define _NORMAPIP * 229 #endif 230 231 232 /* Turn off macro checking systems used by other libraries */ 233 #ifdef CHECK 234 #undef CHECK 235 #endif 236 237 238 /** 239 * ASSERT macro 240 */ 241 #if !defined(_WIN32_WCE) 242 #if defined(BUILD_FOR_SNAP) && defined(CHECKED) 243 # define ASSERT(X) _CHECK(X) 244 #elif defined(DEBUG) 245 # define ASSERT(X) assert(X) 246 #else 247 # define ASSERT(X) 248 #endif 249 #endif 250 251 #if (__GNUC__ >= 3) 252 #define PRINTFLIKE(f, a) __attribute__ ((format(__printf__, f, a))) 253 #else 254 #define PRINTFLIKE(f, a) 255 #endif 256 257 #ifndef NULL 258 #define NULL 0 259 #endif 260 261 262 /** 263 * LONGSTRING macro 264 * gcc -pedantic warns about long string literals, LONGSTRING silences that. 265 */ 266 #if !defined(__GNUC__) 267 # define LONGSTRING 268 #else 269 # define LONGSTRING __extension__ 270 #endif 271 272 273 #ifndef M_PI 274 #define M_PI (3.14159265358979323846) 275 #endif 276 277 #ifndef M_E 278 #define M_E (2.7182818284590452354) 279 #endif 280 281 #ifndef M_LOG2E 282 #define M_LOG2E (1.4426950408889634074) 283 #endif 284 285 #ifndef ONE_DIV_SQRT_LN2 286 #define ONE_DIV_SQRT_LN2 (1.201122408786449815) 287 #endif 288 289 #ifndef FLT_MAX_EXP 290 #define FLT_MAX_EXP 128 291 #endif 292 293 294 /** 295 * USE_IEEE: Determine if we're using IEEE floating point 296 */ 297 #if defined(__i386__) || defined(__386__) || defined(__sparc__) || \ 298 defined(__s390__) || defined(__s390x__) || defined(__powerpc__) || \ 299 defined(__x86_64__) || \ 300 defined(__m68k__) || \ 301 defined(ia64) || defined(__ia64__) || \ 302 defined(__hppa__) || defined(hpux) || \ 303 defined(__mips) || defined(_MIPS_ARCH) || \ 304 defined(__arm__) || \ 305 defined(__sh__) || defined(__m32r__) || \ 306 (defined(__sun) && defined(_IEEE_754)) || \ 307 defined(__alpha__) 308 #define USE_IEEE 309 #define IEEE_ONE 0x3f800000 310 #endif 311 312 313 /** 314 * START/END_FAST_MATH macros: 315 * 316 * START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save 317 * original mode to a temporary). 318 * END_FAST_MATH: Restore x86 FPU to original mode. 319 */ 320 #if defined(__GNUC__) && defined(__i386__) 321 /* 322 * Set the x86 FPU control word to guarantee only 32 bits of precision 323 * are stored in registers. Allowing the FPU to store more introduces 324 * differences between situations where numbers are pulled out of memory 325 * vs. situations where the compiler is able to optimize register usage. 326 * 327 * In the worst case, we force the compiler to use a memory access to 328 * truncate the float, by specifying the 'volatile' keyword. 329 */ 330 /* Hardware default: All exceptions masked, extended double precision, 331 * round to nearest (IEEE compliant): 332 */ 333 #define DEFAULT_X86_FPU 0x037f 334 /* All exceptions masked, single precision, round to nearest: 335 */ 336 #define FAST_X86_FPU 0x003f 337 /* The fldcw instruction will cause any pending FP exceptions to be 338 * raised prior to entering the block, and we clear any pending 339 * exceptions before exiting the block. Hence, asm code has free 340 * reign over the FPU while in the fast math block. 341 */ 342 #if defined(NO_FAST_MATH) 343 #define START_FAST_MATH(x) \ 344 do { \ 345 static GLuint mask = DEFAULT_X86_FPU; \ 346 __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \ 347 __asm__ ( "fldcw %0" : : "m" (mask) ); \ 348 } while (0) 349 #else 350 #define START_FAST_MATH(x) \ 351 do { \ 352 static GLuint mask = FAST_X86_FPU; \ 353 __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \ 354 __asm__ ( "fldcw %0" : : "m" (mask) ); \ 355 } while (0) 356 #endif 357 /* Restore original FPU mode, and clear any exceptions that may have 358 * occurred in the FAST_MATH block. 359 */ 360 #define END_FAST_MATH(x) \ 361 do { \ 362 __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \ 363 } while (0) 364 365 #elif defined(__WATCOMC__) && defined(__386__) 366 #define DEFAULT_X86_FPU 0x037f /* See GCC comments above */ 367 #define FAST_X86_FPU 0x003f /* See GCC comments above */ 368 void _watcom_start_fast_math(unsigned short *x,unsigned short *mask); 369 #pragma aux _watcom_start_fast_math = \ 370 "fnstcw word ptr [eax]" \ 371 "fldcw word ptr [ecx]" \ 372 parm [eax] [ecx] \ 373 modify exact []; 374 void _watcom_end_fast_math(unsigned short *x); 375 #pragma aux _watcom_end_fast_math = \ 376 "fnclex" \ 377 "fldcw word ptr [eax]" \ 378 parm [eax] \ 379 modify exact []; 380 #if defined(NO_FAST_MATH) 381 #define START_FAST_MATH(x) \ 382 do { \ 383 static GLushort mask = DEFAULT_X86_FPU; \ 384 _watcom_start_fast_math(&x,&mask); \ 385 } while (0) 386 #else 387 #define START_FAST_MATH(x) \ 388 do { \ 389 static GLushort mask = FAST_X86_FPU; \ 390 _watcom_start_fast_math(&x,&mask); \ 391 } while (0) 392 #endif 393 #define END_FAST_MATH(x) _watcom_end_fast_math(&x) 394 395 #elif defined(_MSC_VER) && defined(_M_IX86) 396 #define DEFAULT_X86_FPU 0x037f /* See GCC comments above */ 397 #define FAST_X86_FPU 0x003f /* See GCC comments above */ 398 #if defined(NO_FAST_MATH) 399 #define START_FAST_MATH(x) do {\ 400 static GLuint mask = DEFAULT_X86_FPU;\ 401 __asm fnstcw word ptr [x]\ 402 __asm fldcw word ptr [mask]\ 403 } while(0) 404 #else 405 #define START_FAST_MATH(x) do {\ 406 static GLuint mask = FAST_X86_FPU;\ 407 __asm fnstcw word ptr [x]\ 408 __asm fldcw word ptr [mask]\ 409 } while(0) 410 #endif 411 #define END_FAST_MATH(x) do {\ 412 __asm fnclex\ 413 __asm fldcw word ptr [x]\ 414 } while(0) 415 416 #else 417 #define START_FAST_MATH(x) x = 0 418 #define END_FAST_MATH(x) (void)(x) 419 #endif 420 421 422 #ifndef Elements 423 #define Elements(x) (sizeof(x)/sizeof(*(x))) 424 #endif 425 426 427 428 #ifdef __cplusplus 429 } 430 #endif 431 432 433 #endif /* COMPILER_H */ 434