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
65extern "C" {
66#endif
67
68
69#if !defined(__HAIKU__) && !defined(__USE_MISC)
70#if !defined(PIPE_OS_ANDROID)
71typedef unsigned int       uint;
72#endif
73typedef unsigned short     ushort;
74#endif
75typedef unsigned char      ubyte;
76
77typedef 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
256void _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