| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // This code is in the public domain -- Ignacio Castaño <[email protected]>
- #ifndef NV_CORE_DEBUG_H
- #define NV_CORE_DEBUG_H
- #include "nvcore.h"
- #include <stdarg.h> // va_list
- // Make sure we are using our assert.
- #undef assert
- #define NV_ABORT_DEBUG 1
- #define NV_ABORT_IGNORE 2
- #define NV_ABORT_EXIT 3
- #define nvNoAssert(exp) \
- NV_MULTI_LINE_MACRO_BEGIN \
- (void)(false && (exp)); \
- NV_MULTI_LINE_MACRO_END
- #if NV_NO_ASSERT
- # define nvAssert(exp) nvNoAssert(exp)
- # define nvCheck(exp) nvNoAssert(exp)
- # define nvCheckMacro(exp) (exp)
- # define nvDebugAssert(exp) nvNoAssert(exp)
- # define nvDebugCheck(exp) nvNoAssert(exp)
- # define nvDebugBreak() nvNoAssert(0)
- #else // NV_NO_ASSERT
- # if NV_CC_MSVC
- // @@ Does this work in msvc-6 and earlier?
- # define nvDebugBreak() __debugbreak()
- //# define nvDebugBreak() __asm { int 3 }
- # elif NV_OS_ORBIS
- # define nvDebugBreak() __debugbreak()
- # elif NV_CC_GNUC
- # define nvDebugBreak() __builtin_trap()
- # else
- # error "No nvDebugBreak()!"
- # endif
- /*
- # elif NV_CC_GNUC || NV_CPU_PPC && NV_OS_DARWIN
- // @@ Use __builtin_trap() on GCC
- # define nvDebugBreak() __asm__ volatile ("trap")
- # elif (NV_CC_GNUC || NV_CPU_X86 || NV_CPU_X86_64) && NV_OS_DARWIN
- # define nvDebugBreak() __asm__ volatile ("int3")
- # elif NV_CC_GNUC || NV_CPU_X86 || NV_CPU_X86_64
- # define nvDebugBreak() __asm__ ( "int %0" : :"I"(3) )
- # else
- # include <signal.h>
- # define nvDebugBreak() raise(SIGTRAP)
- # endif
- */
- #define nvDebugBreakOnce() \
- NV_MULTI_LINE_MACRO_BEGIN \
- static bool firstTime = true; \
- if (firstTime) { firstTime = false; nvDebugBreak(); } \
- NV_MULTI_LINE_MACRO_END
- #define nvAssertMacro(exp) \
- NV_MULTI_LINE_MACRO_BEGIN \
- if (!(exp)) { \
- if (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) { \
- nvDebugBreak(); \
- } \
- } \
- NV_MULTI_LINE_MACRO_END
- // GCC, LLVM need "##" before the __VA_ARGS__, MSVC doesn't care
- #define nvAssertMacroWithIgnoreAll(exp,...) \
- NV_MULTI_LINE_MACRO_BEGIN \
- static bool ignoreAll = false; \
- if (!ignoreAll && !(exp)) { \
- int result = nvAbort(#exp, __FILE__, __LINE__, __FUNC__, ##__VA_ARGS__); \
- if (result == NV_ABORT_DEBUG) { \
- nvDebugBreak(); \
- } else if (result == NV_ABORT_IGNORE) { \
- ignoreAll = true; \
- } \
- } \
- NV_MULTI_LINE_MACRO_END
- // Interesting assert macro from Insomniac:
- // http://www.gdcvault.com/play/1015319/Developing-Imperfect-Software-How-to
- // Used as follows:
- // if (nvCheck(i < count)) {
- // normal path
- // } else {
- // fixup code.
- // }
- // This style of macro could be combined with __builtin_expect to let the compiler know failure is unlikely.
- #define nvCheckMacro(exp) \
- (\
- (exp) ? true : ( \
- (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) ? (nvDebugBreak(), true) : ( false ) \
- ) \
- )
- #define nvAssert(exp) nvAssertMacro(exp)
- #define nvCheck(exp) nvAssertMacro(exp)
- #if defined(_DEBUG)
- # define nvDebugAssert(exp) nvAssertMacro(exp)
- # define nvDebugCheck(exp) nvAssertMacro(exp)
- #else // _DEBUG
- # define nvDebugAssert(exp) nvNoAssert(exp)
- # define nvDebugCheck(exp) nvNoAssert(exp)
- #endif // _DEBUG
- #endif // NV_NO_ASSERT
- // Use nvAssume for very simple expresions only: nvAssume(0), nvAssume(value == true), etc.
- /*#if !defined(_DEBUG)
- # if NV_CC_MSVC
- # define nvAssume(exp) __assume(exp)
- # else
- # define nvAssume(exp) nvCheck(exp)
- # endif
- #else
- # define nvAssume(exp) nvCheck(exp)
- #endif*/
- #if defined(_DEBUG)
- # if NV_CC_MSVC
- # define nvUnreachable() nvAssert(0 && "unreachable"); __assume(0)
- # else
- # define nvUnreachable() nvAssert(0 && "unreachable"); __builtin_unreachable()
- # endif
- #else
- # if NV_CC_MSVC
- # define nvUnreachable() __assume(0)
- # else
- # define nvUnreachable() __builtin_unreachable()
- # endif
- #endif
- #define nvError(x) nvAbort(x, __FILE__, __LINE__, __FUNC__)
- #define nvWarning(x) nvDebugPrint("*** Warning %s/%d: %s\n", __FILE__, __LINE__, (x))
- #ifndef NV_DEBUG_PRINT
- #define NV_DEBUG_PRINT 1 //defined(_DEBUG)
- #endif
- #if NV_DEBUG_PRINT
- #define nvDebug(...) nvDebugPrint(__VA_ARGS__)
- #else
- #if NV_CC_MSVC
- #define nvDebug(...) __noop(__VA_ARGS__)
- #else
- #define nvDebug(...) ((void)0) // Non-msvc platforms do not evaluate arguments?
- #endif
- #endif
- NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = NULL, const char * msg = NULL, ...) __attribute__((format (printf, 5, 6)));
- NVCORE_API void NV_CDECL nvDebugPrint( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
- namespace nv
- {
- inline bool isValidPtr(const void * ptr) {
- #if NV_CPU_X86_64 || NV_CPU_AARCH64
- if (ptr == NULL) return true;
- if (reinterpret_cast<uint64>(ptr) < 0x10000ULL) return false;
- if (reinterpret_cast<uint64>(ptr) >= 0x000007FFFFFEFFFFULL) return false;
- #else
- if (reinterpret_cast<uint32>(ptr) == 0xcccccccc) return false;
- if (reinterpret_cast<uint32>(ptr) == 0xcdcdcdcd) return false;
- if (reinterpret_cast<uint32>(ptr) == 0xdddddddd) return false;
- if (reinterpret_cast<uint32>(ptr) == 0xffffffff) return false;
- #endif
- return true;
- }
- // Message handler interface.
- struct MessageHandler {
- virtual void log(const char * str, va_list arg) = 0;
- virtual ~MessageHandler() {}
- };
- // Assert handler interface.
- struct AssertHandler {
- virtual int assertion(const char *exp, const char *file, int line, const char *func, const char *msg, va_list arg) = 0;
- virtual ~AssertHandler() {}
- };
- namespace debug
- {
- NVCORE_API void dumpInfo();
- NVCORE_API void dumpCallstack( MessageHandler *messageHandler, int callstackLevelsToSkip = 0 );
- NVCORE_API void setMessageHandler( MessageHandler * messageHandler );
- NVCORE_API void resetMessageHandler();
- NVCORE_API void setAssertHandler( AssertHandler * assertHanlder );
- NVCORE_API void resetAssertHandler();
- NVCORE_API void enableSigHandler(bool interactive);
- NVCORE_API void disableSigHandler();
- NVCORE_API bool isDebuggerPresent();
- NVCORE_API bool attachToDebugger();
- NVCORE_API void terminate(int code);
- }
- } // nv namespace
- #endif // NV_CORE_DEBUG_H
|