230 lines
5.6 KiB
C++
230 lines
5.6 KiB
C++
// Copyright 2007 Georgia Institute of Technology. All rights reserved.
|
|
/**
|
|
* @file compiler.h
|
|
*
|
|
* Defines compiler-specific directives and optimizations. Especially
|
|
* useful are branch-prediction macros "likely" and "unlikely", which
|
|
* can dramatically affect your code's running time.
|
|
*/
|
|
|
|
#ifndef BASE_COMPILER_H
|
|
#define BASE_COMPILER_H
|
|
|
|
/**
|
|
* Begin listing C function prototypes.
|
|
*
|
|
* Needed for proper linking in C++.
|
|
*/
|
|
#ifdef __cplusplus
|
|
#define EXTERN_C_BEGIN extern "C" {
|
|
#else
|
|
#define EXTERN_C_BEGIN
|
|
#endif
|
|
|
|
/**
|
|
* Finish listing C function prototypes.
|
|
*
|
|
* Needed for proper linking in C++.
|
|
*/
|
|
#ifdef __cplusplus
|
|
#define EXTERN_C_END };
|
|
#else
|
|
#define EXTERN_C_END
|
|
#endif
|
|
|
|
/* Check for availability of compiler optimizations and directives. */
|
|
#if !defined(__GNUC__) && !defined(__INTEL_COMPILER)
|
|
#warning Unknown compiler; optimizations and directives disabled.
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define NO_COMPILER_DEFS
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
* Optimize compilation for an expression having a given value.
|
|
*
|
|
* @param expr the expression to evaluate
|
|
* @param value the expected result of expr
|
|
*/
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define expect(expr, value) (__builtin_expect((expr), (value)))
|
|
#else
|
|
#define expect(expr, value) (expr)
|
|
#endif
|
|
|
|
/** Optimize compilation for a condition being true. */
|
|
#define likely(cond) expect(!!(cond), 1)
|
|
|
|
/** Optimize compilation for a condition being false. */
|
|
#define unlikely(cond) expect(!!(cond), 0)
|
|
|
|
/** Returns 1 if the compiler can prove the expression is constant. */
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define IS_CONST_EXPR(expr) (__builtin_constant_p(expr))
|
|
#else
|
|
#define IS_CONST_EXPR(expr) 0
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
* Define a function that never returns, e.g. aborts the program.
|
|
*
|
|
* Supresses potential warning messages about not returning a value in
|
|
* non-void functions.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* COMPILER_NO_RETURN
|
|
* void my_abort();
|
|
* @endcode
|
|
*/
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define COMPILER_NO_RETURN __attribute__((noreturn))
|
|
#else
|
|
#define COMPILER_NO_RETURN
|
|
#endif
|
|
|
|
/**
|
|
* Define a function with printf-style arguments.
|
|
*
|
|
* Enables compile-time warning messages for mismatched printf format
|
|
* strings and argument lists.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* COMPILER_PRINTF(2, 4)
|
|
* void my_printf(int i, const char *format, int j, ...);
|
|
* @endcode
|
|
*
|
|
* Note that C++ member funtions reserve argument 1 for "this", so the
|
|
* first visible argument is 2.
|
|
*/
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define COMPILER_PRINTF(format_arg, dotdotdot_arg) \
|
|
__attribute__((format(printf, format_arg, dotdotdot_arg)))
|
|
#else
|
|
#define COMPILER_PRINTF(format_arg, dotdotdot_arg)
|
|
#endif
|
|
|
|
/**
|
|
* Define a function with no (visible) side-effects.
|
|
*
|
|
* Allows the compiler to optimize out repeated calls or rearrange
|
|
* calls, and supresses warning messages when multiple functions are
|
|
* called in an expression. (By definition, C/C++ may evaluate
|
|
* expressions in any order, causing problems for functions with
|
|
* side-effects).
|
|
*
|
|
* WARNING: due to complier bugs, never use for functions of pointers.
|
|
*
|
|
* Example:
|
|
* @code
|
|
* COMPILER_FUNCTIONAL
|
|
* double my_hypot(double x, double y);
|
|
* @endcode
|
|
*/
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define COMPILER_FUNCTIONAL __attribute__((const))
|
|
#else
|
|
#define COMPILER_FUNCTIONAL
|
|
#endif
|
|
|
|
/**
|
|
* Disables the in-lining of a function.
|
|
*
|
|
* Used to reduce compiled binary size, but rarely worthwhile.
|
|
*/
|
|
#ifndef NO_COMPILER_DEFS
|
|
#define COMPILER_NO_INLINE __attribute__((noinline))
|
|
#else
|
|
#define COMPILER_NO_INLINE
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
* Computes the stride (alignment) of a type.
|
|
*
|
|
* Input must be a type, not a variable as is possible with sizeof.
|
|
*/
|
|
#ifdef __cplusplus
|
|
#define strideof(T) (compiler_strideof<T>::STRIDE)
|
|
template <typename T>
|
|
struct compiler_strideof {
|
|
struct S {T x; char c;};
|
|
/* The compiler gives this stride in a struct. */
|
|
static const int NATURAL_STRIDE =
|
|
(sizeof(S) > sizeof(T)) ? (sizeof(S) - sizeof(T)) : sizeof(T);
|
|
/* This power-of-two stride is likely to be faster. */
|
|
static const int PREFERRED_STRIDE =
|
|
sizeof(T) >= 8 ? 8 : sizeof(T) >= 4 ? 4 : 0;
|
|
/* Use the larger of the two. */
|
|
enum { STRIDE = NATURAL_STRIDE > PREFERRED_STRIDE
|
|
? NATURAL_STRIDE : PREFERRED_STRIDE };
|
|
};
|
|
#else
|
|
#define strideof(T) (sizeof(struct {T x; char c;}) - sizeof(T))
|
|
#endif
|
|
|
|
/** Aligns a size_t to a multiple of a type's stride, rounding up. */
|
|
#define stride_align(num, T) \
|
|
(((size_t)(num) + strideof(T) - 1) / strideof(T) * strideof(T))
|
|
|
|
/** The maximum stride of any object on the platform. */
|
|
#define MAX_STRIDE 16 /* TODO: confirm correct */
|
|
|
|
/** Aligns a size_t to a multiple of the maximum stride. */
|
|
#define stride_align_max(num) \
|
|
(((size_t)(num) + MAX_STRIDE - 1) & ~(size_t)(MAX_STRIDE - 1))
|
|
|
|
/* Fill possibly lacking definition for member memory offsets. */
|
|
#ifndef offsetof
|
|
#define offsetof(S, member) ((size_t)(&((S const *)0)->member))
|
|
#endif
|
|
|
|
|
|
|
|
/** Performs C++ casts in either C or C++. */
|
|
#ifdef __cplusplus
|
|
#define COMPILER_CAST(cast, T, val) (cast< T >(val))
|
|
#else
|
|
#define COMPILER_CAST(cast, T, val) ((T)(val))
|
|
#endif
|
|
|
|
/**
|
|
* Performs the equivalent of static_cast in either C or C++.
|
|
*
|
|
* This is useful if you compile with -Wold-style-cast.
|
|
*/
|
|
#define STATIC_CAST(T, val) COMPILER_CAST(static_cast, T, val)
|
|
|
|
/**
|
|
* Performs the equivalent of reinterpret_cast in either C or C++.
|
|
*
|
|
* This is useful if you compile with -Wold-style-cast.
|
|
*/
|
|
#define REINTERPRET_CAST(T, val) COMPILER_CAST(reinterpret_cast, T, val)
|
|
|
|
|
|
|
|
/** Use a constant reference in C++, or constant pointer in C. */
|
|
#ifdef __cplusplus
|
|
#define CONST_REF const &
|
|
#else
|
|
#define CONST_REF const *
|
|
#endif
|
|
|
|
/** Use a reference in C++, or pointer in C. */
|
|
#ifdef __cplusplus
|
|
#define REF &
|
|
#else
|
|
#define REF *
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* BASE_COMPILER_H */
|