diff options
author | David Greene <greened@obbligato.org> | 2009-12-23 16:39:06 +0000 |
---|---|---|
committer | David Greene <greened@obbligato.org> | 2009-12-23 16:39:06 +0000 |
commit | b5d568cc70506c4cb3aa7abc3370d3ac9411b4a0 (patch) | |
tree | c1d4cee8a7c672a89209661aca67e62e9c67ac34 | |
parent | e59011e7d913b59dd244b0295a984dcfe7976e72 (diff) | |
download | external_llvm-b5d568cc70506c4cb3aa7abc3370d3ac9411b4a0.zip external_llvm-b5d568cc70506c4cb3aa7abc3370d3ac9411b4a0.tar.gz external_llvm-b5d568cc70506c4cb3aa7abc3370d3ac9411b4a0.tar.bz2 |
Provide dbgs(), a circular-buffering debug output stream. By default it
simply passes output to errs(). If -debug-buffer-size=N is set N > 0,
dbgs() buffers its output until program termination and dumps the last N
characters sent to it. This is handy when debugging very large inputs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92002 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Support/Debug.h | 21 | ||||
-rw-r--r-- | lib/Support/Debug.cpp | 56 |
2 files changed, 73 insertions, 4 deletions
diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index e8bc0ce..7395984 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -28,6 +28,8 @@ namespace llvm { +class raw_ostream; + /// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes /// all of their DEBUG statements to be activatable with -debug-only=thatstring. #ifndef DEBUG_TYPE @@ -58,7 +60,7 @@ void SetCurrentDebugType(const char *Type); /// this is a debug build, then the code specified as the option to the macro /// will be executed. Otherwise it will not be. Example: /// -/// DEBUG_WITH_TYPE("bitset", errs() << "Bitset contains: " << Bitset << "\n"); +/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n"); /// /// This will emit the debug information if -debug is present, and -debug-only /// is not specified, or is specified as "bitset". @@ -72,15 +74,28 @@ void SetCurrentDebugType(const char *Type); #define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) #endif +/// EnableDebugBuffering - This defaults to false. If true, the debug +/// stream will install signal handlers to dump any buffered debug +/// output. It allows clients to selectively allow the debug stream +/// to install signal handlers if they are certain there will be no +/// conflict. +/// +extern bool EnableDebugBuffering; + +/// dbgs() - This returns a reference to a raw_ostream for debugging +/// messages. If debugging is disabled it returns dbgs(). Use it +/// like: dbgs() << "foo" << "bar"; +raw_ostream &dbgs(); + // DEBUG macro - This macro should be used by passes to emit debug information. // In the '-debug' option is specified on the commandline, and if this is a // debug build, then the code specified as the option to the macro will be // executed. Otherwise it will not be. Example: // -// DEBUG(errs() << "Bitset contains: " << Bitset << "\n"); +// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); // #define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) - + } // End llvm namespace #endif diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp index 50abe01..12b38c7 100644 --- a/lib/Support/Debug.cpp +++ b/lib/Support/Debug.cpp @@ -25,6 +25,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/circular_raw_ostream.h" +#include "llvm/System/Signals.h" + using namespace llvm; // All Debug.h functionality is a no-op in NDEBUG mode. @@ -37,6 +40,16 @@ static cl::opt<bool, true> Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag)); +// -debug-buffer-size - Buffer the last N characters of debug output +//until program termination. +static cl::opt<unsigned> +DebugBufferSize("debug-buffer-size", + cl::desc("Buffer the last N characters of debug output" + "until program termination. " + "[default 0 -- immediate print-out]"), + cl::Hidden, + cl::init(0)); + static std::string CurrentDebugType; static struct DebugOnlyOpt { void operator=(const std::string &Val) const { @@ -50,6 +63,18 @@ DebugOnly("debug-only", cl::desc("Enable a specific type of debug output"), cl::Hidden, cl::value_desc("debug string"), cl::location(DebugOnlyOptLoc), cl::ValueRequired); +// Signal handlers - dump debug output on termination. +static void debug_user_sig_handler(void *Cookie) +{ + // This is a bit sneaky. Since this is under #ifndef NDEBUG, we + // know that debug mode is enabled and dbgs() really is a + // circular_raw_ostream. If NDEBUG is defined, then dbgs() == + // errs() but this will never be invoked. + llvm::circular_raw_ostream *dbgout = + static_cast<llvm::circular_raw_ostream *>(&llvm::dbgs()); + dbgout->flushBufferWithBanner(); +} + // isCurrentDebugType - Return true if the specified string is the debug type // specified on the command line, or if none was specified on the command line // with the -debug-only=X option. @@ -66,9 +91,38 @@ void llvm::SetCurrentDebugType(const char *Type) { CurrentDebugType = Type; } +/// dbgs - Return a circular-buffered debug stream. +raw_ostream &llvm::dbgs() { + // Do one-time initialization in a thread-safe way. + static struct dbgstream { + circular_raw_ostream strm; + + dbgstream() : + strm(errs(), "*** Debug Log Output ***\n", + (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) { + if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0) + // TODO: Add a handler for SIGUSER1-type signals so the user can + // force a debug dump. + sys::AddSignalHandler(&debug_user_sig_handler, 0); + // Otherwise we've already set the debug stream buffer size to + // zero, disabling buffering. + } + } thestrm; + + return thestrm.strm; +} + #else // Avoid "has no symbols" warning. namespace llvm { -int Debug_dummy = 0; + /// dbgs - Return dbgs(). + raw_ostream &dbgs() { + return dbgs(); + } } + #endif + +/// EnableDebugBuffering - Turn on signal handler installation. +/// +bool llvm::EnableDebugBuffering = false; |