X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FDebug.cpp;h=73aa3b06b7578167f95e55f0ebfa33f921e88b09;hb=678af17920c33ca7ec1178f861a62d540937ec35;hp=71ff411def2b018907ac8e7ae9455f2145e7828f;hpb=43ed267db3512823a9698f810be4e64bee227270;p=oota-llvm.git diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp index 71ff411def2..73aa3b06b75 100644 --- a/lib/Support/Debug.cpp +++ b/lib/Support/Debug.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements a handle way of adding debugging information to your +// This file implements a handy way of adding debugging information to your // code, without it being enabled all of the time, and without having to add // command line options to enable it. // @@ -18,13 +18,17 @@ // can specify '-debug-only=foo' to enable JUST the debug information for the // foo class. // -// When compiling in release mode, the -debug-* options and all code in DEBUG() -// statements disappears, so it does not effect the runtime of the code. +// When compiling without assertions, the -debug-* options and all code in +// DEBUG() statements disappears, so it does not affect the runtime of the code. // //===----------------------------------------------------------------------===// -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/circular_raw_ostream.h" +#include "llvm/Support/ManagedStatic.h" + using namespace llvm; // All Debug.h functionality is a no-op in NDEBUG mode. @@ -37,27 +41,106 @@ static cl::opt Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag)); -static std::string CurrentDebugType; -static struct DebugOnlyOpt { +// -debug-buffer-size - Buffer the last N characters of debug output +//until program termination. +static cl::opt +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 ManagedStatic > CurrentDebugType; + +namespace { + +struct DebugOnlyOpt { void operator=(const std::string &Val) const { - DebugFlag |= !Val.empty(); - CurrentDebugType = Val; + if (Val.empty()) + return; + DebugFlag = true; + CurrentDebugType->push_back(Val); } -} DebugOnlyOptLoc; +}; + +} + +static DebugOnlyOpt DebugOnlyOptLoc; static cl::opt > DebugOnly("debug-only", cl::desc("Enable a specific type of debug output"), - cl::Hidden, cl::value_desc("debug string"), + cl::Hidden, cl::ZeroOrMore, 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::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. // bool llvm::isCurrentDebugType(const char *DebugType) { - return CurrentDebugType.empty() || DebugType == CurrentDebugType; + if (CurrentDebugType->empty()) + return true; + // see if DebugType is in list. Note: do not use find() as that forces us to + // unnecessarily create an std::string instance. + for (auto d : *CurrentDebugType) { + if (d == DebugType) + return true; + } + return false; } + +/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void llvm::setCurrentDebugType(const char *Type) { + CurrentDebugType->clear(); + CurrentDebugType->push_back(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, nullptr); + // Otherwise we've already set the debug stream buffer size to + // zero, disabling buffering so it will output directly to errs(). + } + } thestrm; + + return thestrm.strm; +} + #else // Avoid "has no symbols" warning. -int Debug_dummy = 0; +namespace llvm { + /// dbgs - Return errs(). + raw_ostream &dbgs() { + return errs(); + } +} + #endif + +/// EnableDebugBuffering - Turn on signal handler installation. +/// +bool llvm::EnableDebugBuffering = false;