1//===-- Debug.cpp - An easy way to add debug output to your code ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements a handy way of adding debugging information to your
10// code, without it being enabled all of the time, and without having to add
11// command line options to enable it.
12//
13// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will
14// be enabled automatically if you specify '-debug' on the command-line.
15// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify
16// that your debug code belongs to class "foo".  Then, on the command line, you
17// can specify '-debug-only=foo' to enable JUST the debug information for the
18// foo class.
19//
20// When compiling without assertions, the -debug-* options and all code in
21// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the
22// code.
23//
24//===----------------------------------------------------------------------===//
25
26#include "llvm/Support/Debug.h"
27#include "llvm/Support/CommandLine.h"
28#include "llvm/Support/ManagedStatic.h"
29#include "llvm/Support/Signals.h"
30#include "llvm/Support/circular_raw_ostream.h"
31#include "llvm/Support/raw_ostream.h"
32
33#undef isCurrentDebugType
34#undef setCurrentDebugType
35#undef setCurrentDebugTypes
36
37using namespace llvm;
38
39// Even though LLVM might be built with NDEBUG, define symbols that the code
40// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
41namespace llvm {
42/// Exported boolean set by the -debug option.
43bool DebugFlag = false;
44
45static ManagedStatic<std::vector<std::string>> CurrentDebugType;
46
47/// Return true if the specified string is the debug type
48/// specified on the command line, or if none was specified on the command line
49/// with the -debug-only=X option.
50bool isCurrentDebugType(const char *DebugType) {
51  if (CurrentDebugType->empty())
52    return true;
53  // See if DebugType is in list. Note: do not use find() as that forces us to
54  // unnecessarily create an std::string instance.
55  for (auto &d : *CurrentDebugType) {
56    if (d == DebugType)
57      return true;
58  }
59  return false;
60}
61
62/// Set the current debug type, as if the -debug-only=X
63/// option were specified.  Note that DebugFlag also needs to be set to true for
64/// debug output to be produced.
65///
66void setCurrentDebugTypes(const char **Types, unsigned Count);
67
68void setCurrentDebugType(const char *Type) {
69  setCurrentDebugTypes(&Type, 1);
70}
71
72void setCurrentDebugTypes(const char **Types, unsigned Count) {
73  CurrentDebugType->clear();
74  for (size_t T = 0; T < Count; ++T)
75    CurrentDebugType->push_back(Types[T]);
76}
77} // namespace llvm
78
79// All Debug.h functionality is a no-op in NDEBUG mode.
80#ifndef NDEBUG
81
82// -debug - Command line option to enable the DEBUG statements in the passes.
83// This flag may only be enabled in debug builds.
84static cl::opt<bool, true>
85Debug("debug", cl::desc("Enable debug output"), cl::Hidden,
86      cl::location(DebugFlag));
87
88// -debug-buffer-size - Buffer the last N characters of debug output
89//until program termination.
90static cl::opt<unsigned>
91DebugBufferSize("debug-buffer-size",
92                cl::desc("Buffer the last N characters of debug output "
93                         "until program termination. "
94                         "[default 0 -- immediate print-out]"),
95                cl::Hidden,
96                cl::init(0));
97
98namespace {
99
100struct DebugOnlyOpt {
101  void operator=(const std::string &Val) const {
102    if (Val.empty())
103      return;
104    DebugFlag = true;
105    SmallVector<StringRef,8> dbgTypes;
106    StringRef(Val).split(dbgTypes, ',', -1, false);
107    for (auto dbgType : dbgTypes)
108      CurrentDebugType->push_back(dbgType);
109  }
110};
111
112}
113
114static DebugOnlyOpt DebugOnlyOptLoc;
115
116static cl::opt<DebugOnlyOpt, true, cl::parser<std::string> >
117DebugOnly("debug-only", cl::desc("Enable a specific type of debug output (comma separated list of types)"),
118          cl::Hidden, cl::ZeroOrMore, cl::value_desc("debug string"),
119          cl::location(DebugOnlyOptLoc), cl::ValueRequired);
120// Signal handlers - dump debug output on termination.
121static void debug_user_sig_handler(void *Cookie) {
122  // This is a bit sneaky.  Since this is under #ifndef NDEBUG, we
123  // know that debug mode is enabled and dbgs() really is a
124  // circular_raw_ostream.  If NDEBUG is defined, then dbgs() ==
125  // errs() but this will never be invoked.
126  llvm::circular_raw_ostream &dbgout =
127      static_cast<circular_raw_ostream &>(llvm::dbgs());
128  dbgout.flushBufferWithBanner();
129}
130
131/// dbgs - Return a circular-buffered debug stream.
132raw_ostream &llvm::dbgs() {
133  // Do one-time initialization in a thread-safe way.
134  static struct dbgstream {
135    circular_raw_ostream strm;
136
137    dbgstream() :
138        strm(errs(), "*** Debug Log Output ***\n",
139             (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) {
140      if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0)
141        // TODO: Add a handler for SIGUSER1-type signals so the user can
142        // force a debug dump.
143        sys::AddSignalHandler(&debug_user_sig_handler, nullptr);
144      // Otherwise we've already set the debug stream buffer size to
145      // zero, disabling buffering so it will output directly to errs().
146    }
147  } thestrm;
148
149  return thestrm.strm;
150}
151
152#else
153// Avoid "has no symbols" warning.
154namespace llvm {
155  /// dbgs - Return errs().
156  raw_ostream &dbgs() {
157    return errs();
158  }
159}
160
161#endif
162
163/// EnableDebugBuffering - Turn on signal handler installation.
164///
165bool llvm::EnableDebugBuffering = false;
166