Here's the patch to provide dbgs(). By default it works just like errs(). When -debug-buffer-size=N (N > 0) is set, it buffers output sent to it and dumps it at program termination via a signal handler. Please review. Thanks! -Dave Index: include/llvm/Support/Debug.h ==================================================================--- include/llvm/Support/Debug.h (revision 91557) +++ include/llvm/Support/Debug.h (working copy) @@ -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 @@ -72,15 +74,20 @@ #define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) #endif +/// dbgs() - This returns a reference to a raw_ostream for debugging +/// messages. If debugging is disabled it returns errs(). 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 Index: lib/Support/Debug.cpp ==================================================================--- lib/Support/Debug.cpp (revision 91557) +++ lib/Support/Debug.cpp (working copy) @@ -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,15 @@ Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag)); +// -debug-buffer-size - This is a command line op0tion to set the size +// of the debug stream circular buffer. The value is the number of +// characters to save. +static cl::opt<unsigned> +DebugBufferSize("debug-buffer-size", + llvm::cl::desc("Save last N characters of debug output " + "[default 0--immediate print-out]"), + llvm::cl::init(0)); + static std::string CurrentDebugType; static struct DebugOnlyOpt { void operator=(const std::string &Val) const { @@ -50,6 +62,16 @@ 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) +{ + llvm::circular_raw_ostream *logout + dynamic_cast<llvm::circular_raw_ostream *>(&llvm::dbgs()); + if (logout) { + logout->dumpLog(); + } +} + // 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 +88,29 @@ CurrentDebugType = Type; } +/// dbgs - Return a circular-buffered debug stream. +raw_ostream &llvm::dbgs() { + static circular_raw_ostream strm(errs(), DebugBufferSize); + + static bool initialized = false; + if (!initialized) { + initialized = true; + + sys::AddSignalHandler(&debug_user_sig_handler, 0); + // TODO: Add a handler for SIGUSER1-type signals so the user can + // force a debug dump. + } + + return strm; +} + #else // Avoid "has no symbols" warning. namespace llvm { -int Debug_dummy = 0; + /// dbgs - Return errs(). + raw_ostream &dbgs() { + return errs(); + } } + #endif
On Dec 17, 2009, at 4:02 PM, David Greene wrote:> Here's the patch to provide dbgs(). By default it works just like > errs(). > When -debug-buffer-size=N (N > 0) is set, it buffers output sent to > it and > dumps it at program termination via a signal handler. > > Please review. Thanks! > > -Dave > > Index: include/llvm/Support/Debug.h > ==================================================================> --- include/llvm/Support/Debug.h (revision 91557)Ok.> +++ lib/Support/Debug.cpp (working copy) > @@ -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,15 @@ > Debug("debug", cl::desc("Enable debug output"), cl::Hidden, > cl::location(DebugFlag)); > > +// -debug-buffer-size - This is a command line op0tion to set the > size > +// of the debug stream circular buffer. The value is the number of > +// characters to save. > +static cl::opt<unsigned> > +DebugBufferSize("debug-buffer-size", > + llvm::cl::desc("Save last N characters of debug > output "How about "Buffer the last N characters of debug output until program termination". This should probably also be cl::Hidden.> +// Signal handlers - dump debug output on termination. > +static void debug_user_sig_handler(void *Cookie) > +{ > + llvm::circular_raw_ostream *logout > + dynamic_cast<llvm::circular_raw_ostream *>(&llvm::dbgs());Please do not use dynamic_cast, we're trying to eliminate the last RTTI use in the compiler.> +/// dbgs - Return a circular-buffered debug stream. > +raw_ostream &llvm::dbgs() { > + static circular_raw_ostream strm(errs(), DebugBufferSize); > + > + static bool initialized = false; > + if (!initialized) { > + initialized = true;This isn't thread safe. A way to fix this is to do something like: static struct dbgstream { circular_raw_ostream strm; dbgstream() : strm(errs(), DebugBufferSize) { your one time init stuff here. } } thestrm; return thestrm.strm; Please commit with the appropriate fixes when we settle on the stream design. -Chris
On Friday 18 December 2009 19:56, Chris Lattner wrote:> > +// -debug-buffer-size - This is a command line op0tion to set the > > size > > +// of the debug stream circular buffer. The value is the number of > > +// characters to save. > > +static cl::opt<unsigned> > > +DebugBufferSize("debug-buffer-size", > > + llvm::cl::desc("Save last N characters of debug > > output " > > How about "Buffer the last N characters of debug output until program > termination". This should probably also be cl::Hidden.Ok.> > +// Signal handlers - dump debug output on termination. > > +static void debug_user_sig_handler(void *Cookie) > > +{ > > + llvm::circular_raw_ostream *logout > > + dynamic_cast<llvm::circular_raw_ostream *>(&llvm::dbgs()); > > Please do not use dynamic_cast, we're trying to eliminate the last > RTTI use in the compiler.Do you want me to use dyn_cast? That means I'll have to add some more stuff to raw_ostream and circular_raw_ostream. Or I think I can just assume (Yikes!) that if the signal handler is invoked it will really be a circular_raw_ostream since the handler should (!) only be set up in debug mode. That scares me a bit, though.> > +/// dbgs - Return a circular-buffered debug stream. > > +raw_ostream &llvm::dbgs() { > > + static circular_raw_ostream strm(errs(), DebugBufferSize); > > + > > + static bool initialized = false; > > + if (!initialized) { > > + initialized = true; > > This isn't thread safe. A way to fix this is to do something like: > > static struct dbgstream { > circular_raw_ostream strm; > > dbgstream() : strm(errs(), DebugBufferSize) { > your one time init stuff here. > } > } thestrm; > > return thestrm.strm;Ok.> Please commit with the appropriate fixes when we settle on the stream > design.All right. -Dave