1 /************************************************************************** 2 * 3 * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #ifndef P_COMPILER_H 29 #define P_COMPILER_H 30 31 32 #include "p_config.h" 33 34 #include <stdlib.h> 35 #include <string.h> 36 #include <stddef.h> 37 #include <stdarg.h> 38 #include <limits.h> 39 40 41 #if defined(_WIN32) && !defined(__WIN32__) 42 #define __WIN32__ 43 #endif 44 45 #if defined(_MSC_VER) 46 47 /* Avoid 'expression is always true' warning */ 48 #pragma warning(disable: 4296) 49 50 #endif /* _MSC_VER */ 51 52 53 /* 54 * Alternative stdint.h and stdbool.h headers are supplied in include/c99 for 55 * systems that lack it. 56 */ 57 #ifndef __STDC_LIMIT_MACROS 58 #define __STDC_LIMIT_MACROS 1 59 #endif 60 #include <stdint.h> 61 #include <stdbool.h> 62 63 64 #ifdef __cplusplus 65 extern "C" { 66 #endif 67 68 69 #if !defined(__HAIKU__) && !defined(__USE_MISC) 70 #if !defined(PIPE_OS_ANDROID) 71 typedef unsigned int uint; 72 #endif 73 typedef unsigned short ushort; 74 #endif 75 typedef unsigned char ubyte; 76 77 typedef unsigned char boolean; 78 #ifndef TRUE 79 #define TRUE true 80 #endif 81 #ifndef FALSE 82 #define FALSE false 83 #endif 84 85 #ifndef va_copy 86 #ifdef __va_copy 87 #define va_copy(dest, src) __va_copy((dest), (src)) 88 #else 89 #define va_copy(dest, src) (dest) = (src) 90 #endif 91 #endif 92 93 /* Function inlining */ 94 #ifndef inline 95 # ifdef __cplusplus 96 /* C++ supports inline keyword */ 97 # elif defined(__GNUC__) 98 # define inline __inline__ 99 # elif defined(_MSC_VER) 100 # define inline __inline 101 # elif defined(__ICL) 102 # define inline __inline 103 # elif defined(__INTEL_COMPILER) 104 /* Intel compiler supports inline keyword */ 105 # elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100) 106 # define inline __inline 107 # elif defined(__SUNPRO_C) && defined(__C99FEATURES__) 108 /* C99 supports inline keyword */ 109 # elif (__STDC_VERSION__ >= 199901L) 110 /* C99 supports inline keyword */ 111 # else 112 # define inline 113 # endif 114 #endif 115 #ifndef INLINE 116 # define INLINE inline 117 #endif 118 119 /* Forced function inlining */ 120 #ifndef ALWAYS_INLINE 121 # ifdef __GNUC__ 122 # define ALWAYS_INLINE inline __attribute__((always_inline)) 123 # elif defined(_MSC_VER) 124 # define ALWAYS_INLINE __forceinline 125 # else 126 # define ALWAYS_INLINE INLINE 127 # endif 128 #endif 129 130 /* 131 * Define the C99 restrict keyword. 132 * 133 * See also: 134 * - http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html 135 */ 136 #ifndef restrict 137 # if (__STDC_VERSION__ >= 199901L) 138 /* C99 */ 139 # elif defined(__SUNPRO_C) && defined(__C99FEATURES__) 140 /* C99 */ 141 # elif defined(__GNUC__) 142 # define restrict __restrict__ 143 # elif defined(_MSC_VER) 144 # define restrict __restrict 145 # else 146 # define restrict /* */ 147 # endif 148 #endif 149 150 151 /* Function visibility */ 152 #ifndef PUBLIC 153 # if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 154 # define PUBLIC __attribute__((visibility("default"))) 155 # elif defined(_MSC_VER) 156 # define PUBLIC __declspec(dllexport) 157 # else 158 # define PUBLIC 159 # endif 160 #endif 161 162 163 /* The __FUNCTION__ gcc variable is generally only used for debugging. 164 * If we're not using gcc, define __FUNCTION__ as a cpp symbol here. 165 */ 166 #ifndef __FUNCTION__ 167 # if !defined(__GNUC__) 168 # if (__STDC_VERSION__ >= 199901L) /* C99 */ || \ 169 (defined(__SUNPRO_C) && defined(__C99FEATURES__)) 170 # define __FUNCTION__ __func__ 171 # else 172 # define __FUNCTION__ "<unknown>" 173 # endif 174 # endif 175 # if defined(_MSC_VER) && _MSC_VER < 1300 176 # define __FUNCTION__ "<unknown>" 177 # endif 178 #endif 179 #ifndef __func__ 180 # if (__STDC_VERSION__ >= 199901L) || \ 181 (defined(__SUNPRO_C) && defined(__C99FEATURES__)) 182 /* __func__ is part of C99 */ 183 # elif defined(_MSC_VER) 184 # if _MSC_VER >= 1300 185 # define __func__ __FUNCTION__ 186 # else 187 # define __func__ "<unknown>" 188 # endif 189 # endif 190 #endif 191 192 193 194 /* This should match linux gcc cdecl semantics everywhere, so that we 195 * just codegen one calling convention on all platforms. 196 */ 197 #ifdef _MSC_VER 198 #define PIPE_CDECL __cdecl 199 #else 200 #define PIPE_CDECL 201 #endif 202 203 204 205 #if defined(__GNUC__) 206 #define PIPE_DEPRECATED __attribute__((__deprecated__)) 207 #else 208 #define PIPE_DEPRECATED 209 #endif 210 211 212 213 /* Macros for data alignment. */ 214 #if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) || defined(__SUNPRO_CC) 215 216 /* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Type-Attributes.html */ 217 #define PIPE_ALIGN_TYPE(_alignment, _type) _type __attribute__((aligned(_alignment))) 218 219 /* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Variable-Attributes.html */ 220 #define PIPE_ALIGN_VAR(_alignment) __attribute__((aligned(_alignment))) 221 222 #if (__GNUC__ > 4 || (__GNUC__ == 4 &&__GNUC_MINOR__>1)) && !defined(PIPE_ARCH_X86_64) 223 #define PIPE_ALIGN_STACK __attribute__((force_align_arg_pointer)) 224 #else 225 #define PIPE_ALIGN_STACK 226 #endif 227 228 #elif defined(_MSC_VER) 229 230 /* See http://msdn.microsoft.com/en-us/library/83ythb65.aspx */ 231 #define PIPE_ALIGN_TYPE(_alignment, _type) __declspec(align(_alignment)) _type 232 #define PIPE_ALIGN_VAR(_alignment) __declspec(align(_alignment)) 233 234 #define PIPE_ALIGN_STACK 235 236 #elif defined(SWIG) 237 238 #define PIPE_ALIGN_TYPE(_alignment, _type) _type 239 #define PIPE_ALIGN_VAR(_alignment) 240 241 #define PIPE_ALIGN_STACK 242 243 #else 244 245 #error "Unsupported compiler" 246 247 #endif 248 249 250 #if defined(__GNUC__) 251 252 #define PIPE_READ_WRITE_BARRIER() __asm__("":::"memory") 253 254 #elif defined(_MSC_VER) 255 256 void _ReadWriteBarrier(void); 257 #pragma intrinsic(_ReadWriteBarrier) 258 #define PIPE_READ_WRITE_BARRIER() _ReadWriteBarrier() 259 260 #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 261 262 #define PIPE_READ_WRITE_BARRIER() __machine_rw_barrier() 263 264 #else 265 266 #warning "Unsupported compiler" 267 #define PIPE_READ_WRITE_BARRIER() /* */ 268 269 #endif 270 271 272 /* You should use these macros to mark if blocks where the if condition 273 * is either likely to be true, or unlikely to be true. 274 * 275 * This will inform human readers of this fact, and will also inform 276 * the compiler, who will in turn inform the CPU. 277 * 278 * CPUs often start executing code inside the if or the else blocks 279 * without knowing whether the condition is true or not, and will have 280 * to throw the work away if they find out later they executed the 281 * wrong part of the if. 282 * 283 * If these macros are used, the CPU is more likely to correctly predict 284 * the right path, and will avoid speculatively executing the wrong branch, 285 * thus not throwing away work, resulting in better performance. 286 * 287 * In light of this, it is also a good idea to mark as "likely" a path 288 * which is not necessarily always more likely, but that will benefit much 289 * more from performance improvements since it is already much faster than 290 * the other path, or viceversa with "unlikely". 291 * 292 * Example usage: 293 * if(unlikely(do_we_need_a_software_fallback())) 294 * do_software_fallback(); 295 * else 296 * render_with_gpu(); 297 * 298 * The macros follow the Linux kernel convention, and more examples can 299 * be found there. 300 * 301 * Note that profile guided optimization can offer better results, but 302 * needs an appropriate coverage suite and does not inform human readers. 303 */ 304 #ifndef likely 305 # if defined(__GNUC__) 306 # define likely(x) __builtin_expect(!!(x), 1) 307 # define unlikely(x) __builtin_expect(!!(x), 0) 308 # else 309 # define likely(x) (x) 310 # define unlikely(x) (x) 311 # endif 312 #endif 313 314 315 /** 316 * Static (compile-time) assertion. 317 * Basically, use COND to dimension an array. If COND is false/zero the 318 * array size will be -1 and we'll get a compilation error. 319 */ 320 #define STATIC_ASSERT(COND) \ 321 do { \ 322 typedef int static_assertion_failed[(!!(COND))*2-1]; \ 323 } while (0) 324 325 326 #if defined(__cplusplus) 327 } 328 #endif 329 330 331 #endif /* P_COMPILER_H */ 332