debug.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // This code is in the public domain -- Ignacio Castaño <[email protected]>
  2. #ifndef NV_CORE_DEBUG_H
  3. #define NV_CORE_DEBUG_H
  4. #include "nvcore.h"
  5. #include <stdarg.h> // va_list
  6. // Make sure we are using our assert.
  7. #undef assert
  8. #define NV_ABORT_DEBUG 1
  9. #define NV_ABORT_IGNORE 2
  10. #define NV_ABORT_EXIT 3
  11. #define nvNoAssert(exp) \
  12. NV_MULTI_LINE_MACRO_BEGIN \
  13. (void)(false && (exp)); \
  14. NV_MULTI_LINE_MACRO_END
  15. #if NV_NO_ASSERT
  16. # define nvAssert(exp) nvNoAssert(exp)
  17. # define nvCheck(exp) nvNoAssert(exp)
  18. # define nvCheckMacro(exp) (exp)
  19. # define nvDebugAssert(exp) nvNoAssert(exp)
  20. # define nvDebugCheck(exp) nvNoAssert(exp)
  21. # define nvDebugBreak() nvNoAssert(0)
  22. #else // NV_NO_ASSERT
  23. # if NV_CC_MSVC
  24. // @@ Does this work in msvc-6 and earlier?
  25. # define nvDebugBreak() __debugbreak()
  26. //# define nvDebugBreak() __asm { int 3 }
  27. # elif NV_OS_ORBIS
  28. # define nvDebugBreak() __debugbreak()
  29. # elif NV_CC_GNUC
  30. # define nvDebugBreak() __builtin_trap()
  31. # else
  32. # error "No nvDebugBreak()!"
  33. # endif
  34. /*
  35. # elif NV_CC_GNUC || NV_CPU_PPC && NV_OS_DARWIN
  36. // @@ Use __builtin_trap() on GCC
  37. # define nvDebugBreak() __asm__ volatile ("trap")
  38. # elif (NV_CC_GNUC || NV_CPU_X86 || NV_CPU_X86_64) && NV_OS_DARWIN
  39. # define nvDebugBreak() __asm__ volatile ("int3")
  40. # elif NV_CC_GNUC || NV_CPU_X86 || NV_CPU_X86_64
  41. # define nvDebugBreak() __asm__ ( "int %0" : :"I"(3) )
  42. # else
  43. # include <signal.h>
  44. # define nvDebugBreak() raise(SIGTRAP)
  45. # endif
  46. */
  47. #define nvDebugBreakOnce() \
  48. NV_MULTI_LINE_MACRO_BEGIN \
  49. static bool firstTime = true; \
  50. if (firstTime) { firstTime = false; nvDebugBreak(); } \
  51. NV_MULTI_LINE_MACRO_END
  52. #define nvAssertMacro(exp) \
  53. NV_MULTI_LINE_MACRO_BEGIN \
  54. if (!(exp)) { \
  55. if (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) { \
  56. nvDebugBreak(); \
  57. } \
  58. } \
  59. NV_MULTI_LINE_MACRO_END
  60. // GCC, LLVM need "##" before the __VA_ARGS__, MSVC doesn't care
  61. #define nvAssertMacroWithIgnoreAll(exp,...) \
  62. NV_MULTI_LINE_MACRO_BEGIN \
  63. static bool ignoreAll = false; \
  64. if (!ignoreAll && !(exp)) { \
  65. int result = nvAbort(#exp, __FILE__, __LINE__, __FUNC__, ##__VA_ARGS__); \
  66. if (result == NV_ABORT_DEBUG) { \
  67. nvDebugBreak(); \
  68. } else if (result == NV_ABORT_IGNORE) { \
  69. ignoreAll = true; \
  70. } \
  71. } \
  72. NV_MULTI_LINE_MACRO_END
  73. // Interesting assert macro from Insomniac:
  74. // http://www.gdcvault.com/play/1015319/Developing-Imperfect-Software-How-to
  75. // Used as follows:
  76. // if (nvCheck(i < count)) {
  77. // normal path
  78. // } else {
  79. // fixup code.
  80. // }
  81. // This style of macro could be combined with __builtin_expect to let the compiler know failure is unlikely.
  82. #define nvCheckMacro(exp) \
  83. (\
  84. (exp) ? true : ( \
  85. (nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG) ? (nvDebugBreak(), true) : ( false ) \
  86. ) \
  87. )
  88. #define nvAssert(exp) nvAssertMacro(exp)
  89. #define nvCheck(exp) nvAssertMacro(exp)
  90. #if defined(_DEBUG)
  91. # define nvDebugAssert(exp) nvAssertMacro(exp)
  92. # define nvDebugCheck(exp) nvAssertMacro(exp)
  93. #else // _DEBUG
  94. # define nvDebugAssert(exp) nvNoAssert(exp)
  95. # define nvDebugCheck(exp) nvNoAssert(exp)
  96. #endif // _DEBUG
  97. #endif // NV_NO_ASSERT
  98. // Use nvAssume for very simple expresions only: nvAssume(0), nvAssume(value == true), etc.
  99. /*#if !defined(_DEBUG)
  100. # if NV_CC_MSVC
  101. # define nvAssume(exp) __assume(exp)
  102. # else
  103. # define nvAssume(exp) nvCheck(exp)
  104. # endif
  105. #else
  106. # define nvAssume(exp) nvCheck(exp)
  107. #endif*/
  108. #if defined(_DEBUG)
  109. # if NV_CC_MSVC
  110. # define nvUnreachable() nvAssert(0 && "unreachable"); __assume(0)
  111. # else
  112. # define nvUnreachable() nvAssert(0 && "unreachable"); __builtin_unreachable()
  113. # endif
  114. #else
  115. # if NV_CC_MSVC
  116. # define nvUnreachable() __assume(0)
  117. # else
  118. # define nvUnreachable() __builtin_unreachable()
  119. # endif
  120. #endif
  121. #define nvError(x) nvAbort(x, __FILE__, __LINE__, __FUNC__)
  122. #define nvWarning(x) nvDebugPrint("*** Warning %s/%d: %s\n", __FILE__, __LINE__, (x))
  123. #ifndef NV_DEBUG_PRINT
  124. #define NV_DEBUG_PRINT 1 //defined(_DEBUG)
  125. #endif
  126. #if NV_DEBUG_PRINT
  127. #define nvDebug(...) nvDebugPrint(__VA_ARGS__)
  128. #else
  129. #if NV_CC_MSVC
  130. #define nvDebug(...) __noop(__VA_ARGS__)
  131. #else
  132. #define nvDebug(...) ((void)0) // Non-msvc platforms do not evaluate arguments?
  133. #endif
  134. #endif
  135. 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)));
  136. NVCORE_API void NV_CDECL nvDebugPrint( const char *msg, ... ) __attribute__((format (printf, 1, 2)));
  137. namespace nv
  138. {
  139. inline bool isValidPtr(const void * ptr) {
  140. #if NV_CPU_X86_64 || NV_CPU_AARCH64
  141. if (ptr == NULL) return true;
  142. if (reinterpret_cast<uint64>(ptr) < 0x10000ULL) return false;
  143. if (reinterpret_cast<uint64>(ptr) >= 0x000007FFFFFEFFFFULL) return false;
  144. #else
  145. if (reinterpret_cast<uint32>(ptr) == 0xcccccccc) return false;
  146. if (reinterpret_cast<uint32>(ptr) == 0xcdcdcdcd) return false;
  147. if (reinterpret_cast<uint32>(ptr) == 0xdddddddd) return false;
  148. if (reinterpret_cast<uint32>(ptr) == 0xffffffff) return false;
  149. #endif
  150. return true;
  151. }
  152. // Message handler interface.
  153. struct MessageHandler {
  154. virtual void log(const char * str, va_list arg) = 0;
  155. virtual ~MessageHandler() {}
  156. };
  157. // Assert handler interface.
  158. struct AssertHandler {
  159. virtual int assertion(const char *exp, const char *file, int line, const char *func, const char *msg, va_list arg) = 0;
  160. virtual ~AssertHandler() {}
  161. };
  162. namespace debug
  163. {
  164. NVCORE_API void dumpInfo();
  165. NVCORE_API void dumpCallstack( MessageHandler *messageHandler, int callstackLevelsToSkip = 0 );
  166. NVCORE_API void setMessageHandler( MessageHandler * messageHandler );
  167. NVCORE_API void resetMessageHandler();
  168. NVCORE_API void setAssertHandler( AssertHandler * assertHanlder );
  169. NVCORE_API void resetAssertHandler();
  170. NVCORE_API void enableSigHandler(bool interactive);
  171. NVCORE_API void disableSigHandler();
  172. NVCORE_API bool isDebuggerPresent();
  173. NVCORE_API bool attachToDebugger();
  174. NVCORE_API void terminate(int code);
  175. }
  176. } // nv namespace
  177. #endif // NV_CORE_DEBUG_H