1
0
forked from 0ad/0ad
0ad/source/lib/code_annotation.h
janwas 3d45069b3f improvements/additions from work
bits: fix bit_mask for signed types, add SetBitsTo, LeastSignificantBit,
ClearLeastSignificantBit.
add MSR support (read/write via mahaf in kernel mode)
x86_x64: expose family/model
topology: add support for determining core/package from APIC ID.
TSC: report actual frequency for nehalem invariant TSC.
improved UNREACHABLE/ASSUME_UNREACHABLE (avoid ICC warning, add GCC4.5
support)

This was SVN commit r7860.
2010-08-06 13:03:44 +00:00

187 lines
6.4 KiB
C++

/* Copyright (c) 2010 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* macros for code annotation.
*/
#ifndef INCLUDED_CODE_ANNOTATION
#define INCLUDED_CODE_ANNOTATION
/**
* mark a function local variable or parameter as unused and avoid
* the corresponding compiler warning.
* use inside the function body, e.g. void f(int x) { UNUSED2(x); }
**/
#define UNUSED2(param) (void)param;
/**
* mark a function parameter as unused and avoid
* the corresponding compiler warning.
* wrap around the parameter name, e.g. void f(int UNUSED(x))
**/
#define UNUSED(param)
/**
* "unreachable code" helpers
*
* unreachable lines of code are often the source or symptom of subtle bugs.
* they are flagged by compiler warnings; however, the opposite problem -
* erroneously reaching certain spots (e.g. due to missing return statement)
* is worse and not detected automatically.
*
* to defend against this, the programmer can annotate their code to
* indicate to humans that a particular spot should never be reached.
* however, that isn't much help; better is a sentinel that raises an
* error if if it is actually reached. hence, the UNREACHABLE macro.
*
* ironically, if the code guarded by UNREACHABLE works as it should,
* compilers may flag the macro's code as unreachable. this would
* distract from genuine warnings, which is unacceptable.
*
* even worse, compilers differ in their code checking: GCC only complains if
* non-void functions end without returning a value (i.e. missing return
* statement), while VC checks if lines are unreachable (e.g. if they are
* preceded by a return on all paths).
*
* the implementation below enables optimization and automated checking
* without raising warnings.
**/
#define UNREACHABLE // actually defined below.. this is for
# undef UNREACHABLE // CppDoc's benefit only.
// compiler supports ASSUME_UNREACHABLE => allow it to assume the code is
// never reached (improves optimization at the cost of undefined behavior
// if the annotation turns out to be incorrect).
#if HAVE_ASSUME_UNREACHABLE && !CONFIG_PARANOIA
# define UNREACHABLE ASSUME_UNREACHABLE
// otherwise (or if CONFIG_PARANOIA is set), add a user-visible
// warning if the code is reached. note that abort() fails to stop
// ICC from warning about the lack of a return statement, so we
// use an infinite loop instead.
#else
# define UNREACHABLE\
STMT(\
debug_assert(0); /* hit supposedly unreachable code */\
for(;;){};\
)
#endif
/**
convenient specialization of UNREACHABLE for switch statements whose
default can never be reached. example usage:
int x;
switch(x % 2)
{
case 0: break;
case 1: break;
NODEFAULT;
}
**/
#define NODEFAULT default: UNREACHABLE
// generate a symbol containing the line number of the macro invocation.
// used to give a unique name (per file) to types made by cassert.
// we can't prepend __FILE__ to make it globally unique - the filename
// may be enclosed in quotes. PASTE3_HIDDEN__ is needed to make sure
// __LINE__ is expanded correctly.
#define PASTE3_HIDDEN__(a, b, c) a ## b ## c
#define PASTE3__(a, b, c) PASTE3_HIDDEN__(a, b, c)
#define UID__ PASTE3__(LINE_, __LINE__, _)
#define UID2__ PASTE3__(LINE_, __LINE__, _2)
/**
* Compile-time debug_assert. Causes a compile error if the expression
* evaluates to zero/false.
*
* No runtime overhead; may be used anywhere, including file scope.
* Especially useful for testing sizeof types.
*
* @param expr Expression that is expected to evaluate to non-zero at compile-time.
**/
#define cassert(expr) typedef static_assert_<(expr)>::type UID__
template<bool> struct static_assert_;
template<> struct static_assert_<true>
{
typedef int type;
};
/**
* @copydoc cassert(expr)
*
* This version has a less helpful error message, but redefinition doesn't
* trigger warnings.
**/
#define cassert2(expr) extern u8 CASSERT_FAILURE[1][(expr)]
// indicate a class is noncopyable (usually due to const or reference members).
// example:
// class C {
// NONCOPYABLE(C);
// public: // etc.
// };
// this is preferable to inheritance from boost::noncopyable because it
// avoids ICC 11 W4 warnings about non-virtual dtors and suppression of
// the copy assignment operator.
#define NONCOPYABLE(className)\
private:\
className(const className&);\
const className& operator=(const className&)
#if ICC_VERSION
# define ASSUME_ALIGNED(ptr, multiple) __assume_aligned(ptr, multiple)
#else
# define ASSUME_ALIGNED(ptr, multiple)
#endif
// annotate printf-style functions for compile-time type checking.
// fmtpos is the index of the format argument, counting from 1 or
// (if it's a non-static class function) 2; the '...' is assumed
// to come directly after it.
#if GCC_VERSION
# define PRINTF_ARGS(fmtpos) __attribute__ ((format (printf, fmtpos, fmtpos+1)))
# define VPRINTF_ARGS(fmtpos) __attribute__ ((format (printf, fmtpos, 0)))
# if CONFIG_DEHYDRA
# define WPRINTF_ARGS(fmtpos) __attribute__ ((user("format, w, printf, " #fmtpos ", +1")))
# else
# define WPRINTF_ARGS(fmtpos) /* not currently supported in GCC */
# endif
# define VWPRINTF_ARGS(fmtpos) /* not currently supported in GCC */
#else
# define PRINTF_ARGS(fmtpos)
# define VPRINTF_ARGS(fmtpos)
# define WPRINTF_ARGS(fmtpos)
# define VWPRINTF_ARGS(fmtpos)
// TODO: support _Printf_format_string_ for VC9+
#endif
// annotate vararg functions that expect to end with an explicit NULL
#if GCC_VERSION
# define SENTINEL_ARG __attribute__ ((sentinel))
#else
# define SENTINEL_ARG
#endif
#endif // #ifndef INCLUDED_CODE_ANNOTATION