xref: /freebsd/contrib/llvm-project/llvm/lib/Support/Debug.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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 
33*fe6060f1SDimitry Andric #include "DebugOptions.h"
34*fe6060f1SDimitry 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.
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 
700b57cec5SDimitry Andric void setCurrentDebugType(const char *Type) {
710b57cec5SDimitry Andric   setCurrentDebugTypes(&Type, 1);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
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 
84*fe6060f1SDimitry Andric namespace {
85*fe6060f1SDimitry Andric struct CreateDebug {
86*fe6060f1SDimitry Andric   static void *call() {
87*fe6060f1SDimitry Andric     return new cl::opt<bool, true>("debug", cl::desc("Enable debug output"),
88*fe6060f1SDimitry Andric                                    cl::Hidden, cl::location(DebugFlag));
89*fe6060f1SDimitry Andric   }
90*fe6060f1SDimitry Andric };
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric // -debug-buffer-size - Buffer the last N characters of debug output
930b57cec5SDimitry Andric //until program termination.
94*fe6060f1SDimitry Andric struct CreateDebugBufferSize {
95*fe6060f1SDimitry Andric   static void *call() {
96*fe6060f1SDimitry Andric     return new cl::opt<unsigned>(
97*fe6060f1SDimitry 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]"),
101*fe6060f1SDimitry Andric         cl::Hidden, cl::init(0));
102*fe6060f1SDimitry Andric   }
103*fe6060f1SDimitry Andric };
104*fe6060f1SDimitry Andric } // namespace
105*fe6060f1SDimitry Andric 
106*fe6060f1SDimitry Andric // -debug - Command line option to enable the DEBUG statements in the passes.
107*fe6060f1SDimitry Andric // This flag may only be enabled in debug builds.
108*fe6060f1SDimitry Andric static ManagedStatic<cl::opt<bool, true>, CreateDebug> Debug;
109*fe6060f1SDimitry Andric static ManagedStatic<cl::opt<unsigned>, CreateDebugBufferSize> DebugBufferSize;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric namespace {
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric struct DebugOnlyOpt {
1140b57cec5SDimitry 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 };
124*fe6060f1SDimitry Andric } // namespace
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric static DebugOnlyOpt DebugOnlyOptLoc;
1270b57cec5SDimitry Andric 
128*fe6060f1SDimitry Andric namespace {
129*fe6060f1SDimitry Andric struct CreateDebugOnly {
130*fe6060f1SDimitry Andric   static void *call() {
131*fe6060f1SDimitry Andric     return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>(
132*fe6060f1SDimitry Andric         "debug-only",
133*fe6060f1SDimitry Andric         cl::desc("Enable a specific type of debug output (comma separated list "
134*fe6060f1SDimitry Andric                  "of types)"),
1350b57cec5SDimitry Andric         cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"),
1360b57cec5SDimitry Andric         cl::location(DebugOnlyOptLoc), cl::ValueRequired);
137*fe6060f1SDimitry Andric   }
138*fe6060f1SDimitry Andric };
139*fe6060f1SDimitry Andric } // namespace
140*fe6060f1SDimitry Andric 
141*fe6060f1SDimitry Andric static ManagedStatic<cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>,
142*fe6060f1SDimitry Andric                      CreateDebugOnly>
143*fe6060f1SDimitry Andric     DebugOnly;
144*fe6060f1SDimitry Andric 
145*fe6060f1SDimitry Andric void llvm::initDebugOptions() {
146*fe6060f1SDimitry Andric   *Debug;
147*fe6060f1SDimitry Andric   *DebugBufferSize;
148*fe6060f1SDimitry Andric   *DebugOnly;
149*fe6060f1SDimitry Andric }
150*fe6060f1SDimitry Andric 
1510b57cec5SDimitry Andric // Signal handlers - dump debug output on termination.
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.
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 
168*fe6060f1SDimitry Andric     dbgstream()
169*fe6060f1SDimitry Andric         : strm(errs(), "*** Debug Log Output ***\n",
170*fe6060f1SDimitry Andric                (!EnableDebugBuffering || !DebugFlag) ? 0 : *DebugBufferSize) {
171*fe6060f1SDimitry 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().
1870b57cec5SDimitry Andric   raw_ostream &dbgs() {
1880b57cec5SDimitry Andric     return errs();
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric }
191*fe6060f1SDimitry 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