xref: /freebsd/contrib/llvm-project/llvm/lib/Support/Debug.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===-- Debug.cpp - An easy way to add debug output to your code ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements a handy way of adding debugging information to your
100b57cec5SDimitry Andric // code, without it being enabled all of the time, and without having to add
110b57cec5SDimitry Andric // command line options to enable it.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // In particular, just wrap your code with the LLVM_DEBUG() macro, and it will
140b57cec5SDimitry Andric // be enabled automatically if you specify '-debug' on the command-line.
150b57cec5SDimitry Andric // Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify
160b57cec5SDimitry Andric // that your debug code belongs to class "foo".  Then, on the command line, you
170b57cec5SDimitry Andric // can specify '-debug-only=foo' to enable JUST the debug information for the
180b57cec5SDimitry Andric // foo class.
190b57cec5SDimitry Andric //
200b57cec5SDimitry Andric // When compiling without assertions, the -debug-* options and all code in
210b57cec5SDimitry Andric // LLVM_DEBUG() statements disappears, so it does not affect the runtime of the
220b57cec5SDimitry Andric // code.
230b57cec5SDimitry Andric //
240b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
270b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
280b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h"
290b57cec5SDimitry Andric #include "llvm/Support/Signals.h"
300b57cec5SDimitry Andric #include "llvm/Support/circular_raw_ostream.h"
310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
320b57cec5SDimitry Andric 
33fe6060f1SDimitry Andric #include "DebugOptions.h"
34fe6060f1SDimitry Andric 
350b57cec5SDimitry Andric #undef isCurrentDebugType
360b57cec5SDimitry Andric #undef setCurrentDebugType
370b57cec5SDimitry Andric #undef setCurrentDebugTypes
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric using namespace llvm;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric // Even though LLVM might be built with NDEBUG, define symbols that the code
420b57cec5SDimitry Andric // built without NDEBUG can depend on via the llvm/Support/Debug.h header.
430b57cec5SDimitry Andric namespace llvm {
440b57cec5SDimitry Andric /// Exported boolean set by the -debug option.
450b57cec5SDimitry Andric bool DebugFlag = false;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric static ManagedStatic<std::vector<std::string>> CurrentDebugType;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric /// Return true if the specified string is the debug type
500b57cec5SDimitry Andric /// specified on the command line, or if none was specified on the command line
510b57cec5SDimitry Andric /// with the -debug-only=X option.
isCurrentDebugType(const char * DebugType)520b57cec5SDimitry Andric bool isCurrentDebugType(const char *DebugType) {
530b57cec5SDimitry Andric   if (CurrentDebugType->empty())
540b57cec5SDimitry Andric     return true;
550b57cec5SDimitry Andric   // See if DebugType is in list. Note: do not use find() as that forces us to
560b57cec5SDimitry Andric   // unnecessarily create an std::string instance.
570b57cec5SDimitry Andric   for (auto &d : *CurrentDebugType) {
580b57cec5SDimitry Andric     if (d == DebugType)
590b57cec5SDimitry Andric       return true;
600b57cec5SDimitry Andric   }
610b57cec5SDimitry Andric   return false;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric /// Set the current debug type, as if the -debug-only=X
650b57cec5SDimitry Andric /// option were specified.  Note that DebugFlag also needs to be set to true for
660b57cec5SDimitry Andric /// debug output to be produced.
670b57cec5SDimitry Andric ///
680b57cec5SDimitry Andric void setCurrentDebugTypes(const char **Types, unsigned Count);
690b57cec5SDimitry Andric 
setCurrentDebugType(const char * Type)700b57cec5SDimitry Andric void setCurrentDebugType(const char *Type) {
710b57cec5SDimitry Andric   setCurrentDebugTypes(&Type, 1);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
setCurrentDebugTypes(const char ** Types,unsigned Count)740b57cec5SDimitry Andric void setCurrentDebugTypes(const char **Types, unsigned Count) {
750b57cec5SDimitry Andric   CurrentDebugType->clear();
760b57cec5SDimitry Andric   for (size_t T = 0; T < Count; ++T)
770b57cec5SDimitry Andric     CurrentDebugType->push_back(Types[T]);
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric } // namespace llvm
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric // All Debug.h functionality is a no-op in NDEBUG mode.
820b57cec5SDimitry Andric #ifndef NDEBUG
830b57cec5SDimitry Andric 
84fe6060f1SDimitry Andric namespace {
85fe6060f1SDimitry Andric struct CreateDebug {
call__anona2554e630111::CreateDebug86fe6060f1SDimitry Andric   static void *call() {
87fe6060f1SDimitry Andric     return new cl::opt<bool, true>("debug", cl::desc("Enable debug output"),
88fe6060f1SDimitry Andric                                    cl::Hidden, cl::location(DebugFlag));
89fe6060f1SDimitry Andric   }
90fe6060f1SDimitry Andric };
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric // -debug-buffer-size - Buffer the last N characters of debug output
930b57cec5SDimitry Andric //until program termination.
94fe6060f1SDimitry Andric struct CreateDebugBufferSize {
call__anona2554e630111::CreateDebugBufferSize95fe6060f1SDimitry Andric   static void *call() {
96fe6060f1SDimitry Andric     return new cl::opt<unsigned>(
97fe6060f1SDimitry Andric         "debug-buffer-size",
980b57cec5SDimitry Andric         cl::desc("Buffer the last N characters of debug output "
990b57cec5SDimitry Andric                  "until program termination. "
1000b57cec5SDimitry Andric                  "[default 0 -- immediate print-out]"),
101fe6060f1SDimitry Andric         cl::Hidden, cl::init(0));
102fe6060f1SDimitry Andric   }
103fe6060f1SDimitry Andric };
104fe6060f1SDimitry Andric } // namespace
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric // -debug - Command line option to enable the DEBUG statements in the passes.
107fe6060f1SDimitry Andric // This flag may only be enabled in debug builds.
108fe6060f1SDimitry Andric static ManagedStatic<cl::opt<bool, true>, CreateDebug> Debug;
109fe6060f1SDimitry Andric static ManagedStatic<cl::opt<unsigned>, CreateDebugBufferSize> DebugBufferSize;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric namespace {
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric struct DebugOnlyOpt {
operator =__anona2554e630211::DebugOnlyOpt1140b57cec5SDimitry Andric   void operator=(const std::string &Val) const {
1150b57cec5SDimitry Andric     if (Val.empty())
1160b57cec5SDimitry Andric       return;
1170b57cec5SDimitry Andric     DebugFlag = true;
1180b57cec5SDimitry Andric     SmallVector<StringRef,8> dbgTypes;
1190b57cec5SDimitry Andric     StringRef(Val).split(dbgTypes, ',', -1, false);
1200b57cec5SDimitry Andric     for (auto dbgType : dbgTypes)
1215ffd83dbSDimitry Andric       CurrentDebugType->push_back(std::string(dbgType));
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric };
124fe6060f1SDimitry Andric } // namespace
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric static DebugOnlyOpt DebugOnlyOptLoc;
1270b57cec5SDimitry Andric 
128fe6060f1SDimitry Andric namespace {
129fe6060f1SDimitry Andric struct CreateDebugOnly {
call__anona2554e630311::CreateDebugOnly130fe6060f1SDimitry Andric   static void *call() {
131fe6060f1SDimitry Andric     return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>(
132fe6060f1SDimitry Andric         "debug-only",
133fe6060f1SDimitry Andric         cl::desc("Enable a specific type of debug output (comma separated list "
134fe6060f1SDimitry Andric                  "of types)"),
135*81ad6265SDimitry Andric         cl::Hidden, cl::value_desc("debug string"),
1360b57cec5SDimitry Andric         cl::location(DebugOnlyOptLoc), cl::ValueRequired);
137fe6060f1SDimitry Andric   }
138fe6060f1SDimitry Andric };
139fe6060f1SDimitry Andric } // namespace
140fe6060f1SDimitry Andric 
141fe6060f1SDimitry Andric static ManagedStatic<cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>,
142fe6060f1SDimitry Andric                      CreateDebugOnly>
143fe6060f1SDimitry Andric     DebugOnly;
144fe6060f1SDimitry Andric 
initDebugOptions()145fe6060f1SDimitry Andric void llvm::initDebugOptions() {
146fe6060f1SDimitry Andric   *Debug;
147fe6060f1SDimitry Andric   *DebugBufferSize;
148fe6060f1SDimitry Andric   *DebugOnly;
149fe6060f1SDimitry Andric }
150fe6060f1SDimitry Andric 
1510b57cec5SDimitry Andric // Signal handlers - dump debug output on termination.
debug_user_sig_handler(void * Cookie)1520b57cec5SDimitry Andric static void debug_user_sig_handler(void *Cookie) {
1530b57cec5SDimitry Andric   // This is a bit sneaky.  Since this is under #ifndef NDEBUG, we
1540b57cec5SDimitry Andric   // know that debug mode is enabled and dbgs() really is a
1550b57cec5SDimitry Andric   // circular_raw_ostream.  If NDEBUG is defined, then dbgs() ==
1560b57cec5SDimitry Andric   // errs() but this will never be invoked.
1570b57cec5SDimitry Andric   llvm::circular_raw_ostream &dbgout =
1580b57cec5SDimitry Andric       static_cast<circular_raw_ostream &>(llvm::dbgs());
1590b57cec5SDimitry Andric   dbgout.flushBufferWithBanner();
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric /// dbgs - Return a circular-buffered debug stream.
dbgs()1630b57cec5SDimitry Andric raw_ostream &llvm::dbgs() {
1640b57cec5SDimitry Andric   // Do one-time initialization in a thread-safe way.
1650b57cec5SDimitry Andric   static struct dbgstream {
1660b57cec5SDimitry Andric     circular_raw_ostream strm;
1670b57cec5SDimitry Andric 
168fe6060f1SDimitry Andric     dbgstream()
169fe6060f1SDimitry Andric         : strm(errs(), "*** Debug Log Output ***\n",
170fe6060f1SDimitry Andric                (!EnableDebugBuffering || !DebugFlag) ? 0 : *DebugBufferSize) {
171fe6060f1SDimitry Andric       if (EnableDebugBuffering && DebugFlag && *DebugBufferSize != 0)
1720b57cec5SDimitry Andric         // TODO: Add a handler for SIGUSER1-type signals so the user can
1730b57cec5SDimitry Andric         // force a debug dump.
1740b57cec5SDimitry Andric         sys::AddSignalHandler(&debug_user_sig_handler, nullptr);
1750b57cec5SDimitry Andric       // Otherwise we've already set the debug stream buffer size to
1760b57cec5SDimitry Andric       // zero, disabling buffering so it will output directly to errs().
1770b57cec5SDimitry Andric     }
1780b57cec5SDimitry Andric   } thestrm;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   return thestrm.strm;
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric #else
1840b57cec5SDimitry Andric // Avoid "has no symbols" warning.
1850b57cec5SDimitry Andric namespace llvm {
1860b57cec5SDimitry Andric   /// dbgs - Return errs().
dbgs()1870b57cec5SDimitry Andric   raw_ostream &dbgs() {
1880b57cec5SDimitry Andric     return errs();
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric }
initDebugOptions()191fe6060f1SDimitry Andric void llvm::initDebugOptions() {}
1920b57cec5SDimitry Andric #endif
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric /// EnableDebugBuffering - Turn on signal handler installation.
1950b57cec5SDimitry Andric ///
1960b57cec5SDimitry Andric bool llvm::EnableDebugBuffering = false;
197