compiler.h revision 848b8605
1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg 27848b8605Smrg/** 28848b8605Smrg * \file compiler.h 29848b8605Smrg * Compiler-related stuff. 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg 33848b8605Smrg#ifndef COMPILER_H 34848b8605Smrg#define COMPILER_H 35848b8605Smrg 36848b8605Smrg 37848b8605Smrg#include <assert.h> 38848b8605Smrg#include <ctype.h> 39848b8605Smrg#include <math.h> 40848b8605Smrg#include <limits.h> 41848b8605Smrg#include <stdlib.h> 42848b8605Smrg#include <stdio.h> 43848b8605Smrg#include <string.h> 44848b8605Smrg#include <float.h> 45848b8605Smrg#include <stdarg.h> 46848b8605Smrg 47848b8605Smrg#include "util/macros.h" 48848b8605Smrg 49848b8605Smrg#include "c99_compat.h" /* inline, __func__, etc. */ 50848b8605Smrg 51848b8605Smrg 52848b8605Smrg#ifdef __cplusplus 53848b8605Smrgextern "C" { 54848b8605Smrg#endif 55848b8605Smrg 56848b8605Smrg 57848b8605Smrg/** 58848b8605Smrg * Get standard integer types 59848b8605Smrg */ 60848b8605Smrg#include <stdint.h> 61848b8605Smrg 62848b8605Smrg 63848b8605Smrg/** 64848b8605Smrg * Sun compilers define __i386 instead of the gcc-style __i386__ 65848b8605Smrg */ 66848b8605Smrg#ifdef __SUNPRO_C 67848b8605Smrg# if !defined(__i386__) && defined(__i386) 68848b8605Smrg# define __i386__ 69848b8605Smrg# elif !defined(__amd64__) && defined(__amd64) 70848b8605Smrg# define __amd64__ 71848b8605Smrg# elif !defined(__sparc__) && defined(__sparc) 72848b8605Smrg# define __sparc__ 73848b8605Smrg# endif 74848b8605Smrg# if !defined(__volatile) 75848b8605Smrg# define __volatile volatile 76848b8605Smrg# endif 77848b8605Smrg#endif 78848b8605Smrg 79848b8605Smrg 80848b8605Smrg/** 81848b8605Smrg * finite macro. 82848b8605Smrg */ 83848b8605Smrg#if defined(_MSC_VER) 84848b8605Smrg# define finite _finite 85848b8605Smrg#endif 86848b8605Smrg 87848b8605Smrg 88848b8605Smrg/** 89848b8605Smrg * Disable assorted warnings 90848b8605Smrg */ 91848b8605Smrg#if defined(_WIN32) && !defined(__CYGWIN__) 92848b8605Smrg# if !defined(__GNUC__) /* mingw environment */ 93848b8605Smrg# pragma warning( disable : 4068 ) /* unknown pragma */ 94848b8605Smrg# pragma warning( disable : 4710 ) /* function 'foo' not inlined */ 95848b8605Smrg# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */ 96848b8605Smrg# pragma warning( disable : 4127 ) /* conditional expression is constant */ 97848b8605Smrg# if defined(MESA_MINWARN) 98848b8605Smrg# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */ 99848b8605Smrg# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */ 100848b8605Smrg# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */ 101848b8605Smrg# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */ 102848b8605Smrg# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */ 103848b8605Smrg# endif 104848b8605Smrg# endif 105848b8605Smrg#endif 106848b8605Smrg 107848b8605Smrg 108848b8605Smrg 109848b8605Smrg/* XXX: Use standard `inline` keyword instead */ 110848b8605Smrg#ifndef INLINE 111848b8605Smrg# define INLINE inline 112848b8605Smrg#endif 113848b8605Smrg 114848b8605Smrg 115848b8605Smrg/** 116848b8605Smrg * PUBLIC/USED macros 117848b8605Smrg * 118848b8605Smrg * If we build the library with gcc's -fvisibility=hidden flag, we'll 119848b8605Smrg * use the PUBLIC macro to mark functions that are to be exported. 120848b8605Smrg * 121848b8605Smrg * We also need to define a USED attribute, so the optimizer doesn't 122848b8605Smrg * inline a static function that we later use in an alias. - ajax 123848b8605Smrg */ 124848b8605Smrg#ifndef PUBLIC 125848b8605Smrg# if (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 126848b8605Smrg# define PUBLIC __attribute__((visibility("default"))) 127848b8605Smrg# define USED __attribute__((used)) 128848b8605Smrg# else 129848b8605Smrg# define PUBLIC 130848b8605Smrg# define USED 131848b8605Smrg# endif 132848b8605Smrg#endif 133848b8605Smrg 134848b8605Smrg 135848b8605Smrg/* XXX: Use standard `__func__` instead */ 136848b8605Smrg#ifndef __FUNCTION__ 137848b8605Smrg# define __FUNCTION__ __func__ 138848b8605Smrg#endif 139848b8605Smrg 140848b8605Smrg/** 141848b8605Smrg * Either define MESA_BIG_ENDIAN or MESA_LITTLE_ENDIAN, and CPU_TO_LE32. 142848b8605Smrg * Do not use these unless absolutely necessary! 143848b8605Smrg * Try to use a runtime test instead. 144848b8605Smrg * For now, only used by some DRI hardware drivers for color/texel packing. 145848b8605Smrg */ 146848b8605Smrg#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN 147848b8605Smrg#if defined(__linux__) 148848b8605Smrg#include <byteswap.h> 149848b8605Smrg#define CPU_TO_LE32( x ) bswap_32( x ) 150848b8605Smrg#elif defined(__APPLE__) 151848b8605Smrg#include <CoreFoundation/CFByteOrder.h> 152848b8605Smrg#define CPU_TO_LE32( x ) CFSwapInt32HostToLittle( x ) 153848b8605Smrg#elif (defined(_AIX) || defined(__blrts)) 154848b8605Smrgstatic INLINE GLuint CPU_TO_LE32(GLuint x) 155848b8605Smrg{ 156848b8605Smrg return (((x & 0x000000ff) << 24) | 157848b8605Smrg ((x & 0x0000ff00) << 8) | 158848b8605Smrg ((x & 0x00ff0000) >> 8) | 159848b8605Smrg ((x & 0xff000000) >> 24)); 160848b8605Smrg} 161848b8605Smrg#elif defined(__OpenBSD__) 162848b8605Smrg#include <sys/types.h> 163848b8605Smrg#define CPU_TO_LE32( x ) htole32( x ) 164848b8605Smrg#else /*__linux__ */ 165848b8605Smrg#include <sys/endian.h> 166848b8605Smrg#define CPU_TO_LE32( x ) bswap32( x ) 167848b8605Smrg#endif /*__linux__*/ 168848b8605Smrg#define MESA_BIG_ENDIAN 1 169848b8605Smrg#else 170848b8605Smrg#define CPU_TO_LE32( x ) ( x ) 171848b8605Smrg#define MESA_LITTLE_ENDIAN 1 172848b8605Smrg#endif 173848b8605Smrg#define LE32_TO_CPU( x ) CPU_TO_LE32( x ) 174848b8605Smrg 175848b8605Smrg 176848b8605Smrg 177848b8605Smrg#if !defined(CAPI) && defined(_WIN32) 178848b8605Smrg#define CAPI _cdecl 179848b8605Smrg#endif 180848b8605Smrg 181848b8605Smrg 182848b8605Smrg/** 183848b8605Smrg * Create a macro so that asm functions can be linked into compilers other 184848b8605Smrg * than GNU C 185848b8605Smrg */ 186848b8605Smrg#ifndef _ASMAPI 187848b8605Smrg#if defined(_WIN32) 188848b8605Smrg#define _ASMAPI __cdecl 189848b8605Smrg#else 190848b8605Smrg#define _ASMAPI 191848b8605Smrg#endif 192848b8605Smrg#ifdef PTR_DECL_IN_FRONT 193848b8605Smrg#define _ASMAPIP * _ASMAPI 194848b8605Smrg#else 195848b8605Smrg#define _ASMAPIP _ASMAPI * 196848b8605Smrg#endif 197848b8605Smrg#endif 198848b8605Smrg 199848b8605Smrg#ifdef USE_X86_ASM 200848b8605Smrg#define _NORMAPI _ASMAPI 201848b8605Smrg#define _NORMAPIP _ASMAPIP 202848b8605Smrg#else 203848b8605Smrg#define _NORMAPI 204848b8605Smrg#define _NORMAPIP * 205848b8605Smrg#endif 206848b8605Smrg 207848b8605Smrg 208848b8605Smrg/* Turn off macro checking systems used by other libraries */ 209848b8605Smrg#ifdef CHECK 210848b8605Smrg#undef CHECK 211848b8605Smrg#endif 212848b8605Smrg 213848b8605Smrg 214848b8605Smrg/** 215848b8605Smrg * ASSERT macro 216848b8605Smrg */ 217848b8605Smrg#if !defined(_WIN32_WCE) 218848b8605Smrg#if defined(DEBUG) 219848b8605Smrg# define ASSERT(X) assert(X) 220848b8605Smrg#else 221848b8605Smrg# define ASSERT(X) 222848b8605Smrg#endif 223848b8605Smrg#endif 224848b8605Smrg 225848b8605Smrg 226848b8605Smrg/* 227848b8605Smrg * A trick to suppress uninitialized variable warning without generating any 228848b8605Smrg * code 229848b8605Smrg */ 230848b8605Smrg#define uninitialized_var(x) x = x 231848b8605Smrg 232848b8605Smrg#ifndef NULL 233848b8605Smrg#define NULL 0 234848b8605Smrg#endif 235848b8605Smrg 236848b8605Smrg 237848b8605Smrg/** 238848b8605Smrg * LONGSTRING macro 239848b8605Smrg * gcc -pedantic warns about long string literals, LONGSTRING silences that. 240848b8605Smrg */ 241848b8605Smrg#if !defined(__GNUC__) 242848b8605Smrg# define LONGSTRING 243848b8605Smrg#else 244848b8605Smrg# define LONGSTRING __extension__ 245848b8605Smrg#endif 246848b8605Smrg 247848b8605Smrg 248848b8605Smrg#ifndef M_PI 249848b8605Smrg#define M_PI (3.14159265358979323846) 250848b8605Smrg#endif 251848b8605Smrg 252848b8605Smrg#ifndef M_E 253848b8605Smrg#define M_E (2.7182818284590452354) 254848b8605Smrg#endif 255848b8605Smrg 256848b8605Smrg#ifndef M_LOG2E 257848b8605Smrg#define M_LOG2E (1.4426950408889634074) 258848b8605Smrg#endif 259848b8605Smrg 260848b8605Smrg#ifndef ONE_DIV_SQRT_LN2 261848b8605Smrg#define ONE_DIV_SQRT_LN2 (1.201122408786449815) 262848b8605Smrg#endif 263848b8605Smrg 264848b8605Smrg#ifndef FLT_MAX_EXP 265848b8605Smrg#define FLT_MAX_EXP 128 266848b8605Smrg#endif 267848b8605Smrg 268848b8605Smrg#define IEEE_ONE 0x3f800000 269848b8605Smrg 270848b8605Smrg/** 271848b8605Smrg * START/END_FAST_MATH macros: 272848b8605Smrg * 273848b8605Smrg * START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save 274848b8605Smrg * original mode to a temporary). 275848b8605Smrg * END_FAST_MATH: Restore x86 FPU to original mode. 276848b8605Smrg */ 277848b8605Smrg#if defined(__GNUC__) && defined(__i386__) 278848b8605Smrg/* 279848b8605Smrg * Set the x86 FPU control word to guarentee only 32 bits of precision 280848b8605Smrg * are stored in registers. Allowing the FPU to store more introduces 281848b8605Smrg * differences between situations where numbers are pulled out of memory 282848b8605Smrg * vs. situations where the compiler is able to optimize register usage. 283848b8605Smrg * 284848b8605Smrg * In the worst case, we force the compiler to use a memory access to 285848b8605Smrg * truncate the float, by specifying the 'volatile' keyword. 286848b8605Smrg */ 287848b8605Smrg/* Hardware default: All exceptions masked, extended double precision, 288848b8605Smrg * round to nearest (IEEE compliant): 289848b8605Smrg */ 290848b8605Smrg#define DEFAULT_X86_FPU 0x037f 291848b8605Smrg/* All exceptions masked, single precision, round to nearest: 292848b8605Smrg */ 293848b8605Smrg#define FAST_X86_FPU 0x003f 294848b8605Smrg/* The fldcw instruction will cause any pending FP exceptions to be 295848b8605Smrg * raised prior to entering the block, and we clear any pending 296848b8605Smrg * exceptions before exiting the block. Hence, asm code has free 297848b8605Smrg * reign over the FPU while in the fast math block. 298848b8605Smrg */ 299848b8605Smrg#if defined(NO_FAST_MATH) 300848b8605Smrg#define START_FAST_MATH(x) \ 301848b8605Smrgdo { \ 302848b8605Smrg static GLuint mask = DEFAULT_X86_FPU; \ 303848b8605Smrg __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \ 304848b8605Smrg __asm__ ( "fldcw %0" : : "m" (mask) ); \ 305848b8605Smrg} while (0) 306848b8605Smrg#else 307848b8605Smrg#define START_FAST_MATH(x) \ 308848b8605Smrgdo { \ 309848b8605Smrg static GLuint mask = FAST_X86_FPU; \ 310848b8605Smrg __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \ 311848b8605Smrg __asm__ ( "fldcw %0" : : "m" (mask) ); \ 312848b8605Smrg} while (0) 313848b8605Smrg#endif 314848b8605Smrg/* Restore original FPU mode, and clear any exceptions that may have 315848b8605Smrg * occurred in the FAST_MATH block. 316848b8605Smrg */ 317848b8605Smrg#define END_FAST_MATH(x) \ 318848b8605Smrgdo { \ 319848b8605Smrg __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \ 320848b8605Smrg} while (0) 321848b8605Smrg 322848b8605Smrg#elif defined(_MSC_VER) && defined(_M_IX86) 323848b8605Smrg#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */ 324848b8605Smrg#define FAST_X86_FPU 0x003f /* See GCC comments above */ 325848b8605Smrg#if defined(NO_FAST_MATH) 326848b8605Smrg#define START_FAST_MATH(x) do {\ 327848b8605Smrg static GLuint mask = DEFAULT_X86_FPU;\ 328848b8605Smrg __asm fnstcw word ptr [x]\ 329848b8605Smrg __asm fldcw word ptr [mask]\ 330848b8605Smrg} while(0) 331848b8605Smrg#else 332848b8605Smrg#define START_FAST_MATH(x) do {\ 333848b8605Smrg static GLuint mask = FAST_X86_FPU;\ 334848b8605Smrg __asm fnstcw word ptr [x]\ 335848b8605Smrg __asm fldcw word ptr [mask]\ 336848b8605Smrg} while(0) 337848b8605Smrg#endif 338848b8605Smrg#define END_FAST_MATH(x) do {\ 339848b8605Smrg __asm fnclex\ 340848b8605Smrg __asm fldcw word ptr [x]\ 341848b8605Smrg} while(0) 342848b8605Smrg 343848b8605Smrg#else 344848b8605Smrg#define START_FAST_MATH(x) x = 0 345848b8605Smrg#define END_FAST_MATH(x) (void)(x) 346848b8605Smrg#endif 347848b8605Smrg 348848b8605Smrg 349848b8605Smrg#ifndef Elements 350848b8605Smrg#define Elements(x) (sizeof(x)/sizeof(*(x))) 351848b8605Smrg#endif 352848b8605Smrg 353848b8605Smrg#ifdef __cplusplus 354848b8605Smrg} 355848b8605Smrg#endif 356848b8605Smrg 357848b8605Smrg 358848b8605Smrg#endif /* COMPILER_H */ 359