Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Support/Debug.cpp
35232 views
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
#include "DebugOptions.h"
34
35
#undef isCurrentDebugType
36
#undef setCurrentDebugType
37
#undef setCurrentDebugTypes
38
39
using namespace llvm;
40
41
// Even though LLVM might be built with NDEBUG, define symbols that the code
42
// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
43
namespace llvm {
44
/// Exported boolean set by the -debug option.
45
bool DebugFlag = false;
46
47
static ManagedStatic<std::vector<std::string>> CurrentDebugType;
48
49
/// Return true if the specified string is the debug type
50
/// specified on the command line, or if none was specified on the command line
51
/// with the -debug-only=X option.
52
bool isCurrentDebugType(const char *DebugType) {
53
if (CurrentDebugType->empty())
54
return true;
55
// See if DebugType is in list. Note: do not use find() as that forces us to
56
// unnecessarily create an std::string instance.
57
for (auto &d : *CurrentDebugType) {
58
if (d == DebugType)
59
return true;
60
}
61
return false;
62
}
63
64
/// Set the current debug type, as if the -debug-only=X
65
/// option were specified. Note that DebugFlag also needs to be set to true for
66
/// debug output to be produced.
67
///
68
void setCurrentDebugTypes(const char **Types, unsigned Count);
69
70
void setCurrentDebugType(const char *Type) {
71
setCurrentDebugTypes(&Type, 1);
72
}
73
74
void setCurrentDebugTypes(const char **Types, unsigned Count) {
75
CurrentDebugType->clear();
76
for (size_t T = 0; T < Count; ++T)
77
CurrentDebugType->push_back(Types[T]);
78
}
79
} // namespace llvm
80
81
// All Debug.h functionality is a no-op in NDEBUG mode.
82
#ifndef NDEBUG
83
84
namespace {
85
struct CreateDebug {
86
static void *call() {
87
return new cl::opt<bool, true>("debug", cl::desc("Enable debug output"),
88
cl::Hidden, cl::location(DebugFlag));
89
}
90
};
91
92
// -debug-buffer-size - Buffer the last N characters of debug output
93
//until program termination.
94
struct CreateDebugBufferSize {
95
static void *call() {
96
return new cl::opt<unsigned>(
97
"debug-buffer-size",
98
cl::desc("Buffer the last N characters of debug output "
99
"until program termination. "
100
"[default 0 -- immediate print-out]"),
101
cl::Hidden, cl::init(0));
102
}
103
};
104
} // namespace
105
106
// -debug - Command line option to enable the DEBUG statements in the passes.
107
// This flag may only be enabled in debug builds.
108
static ManagedStatic<cl::opt<bool, true>, CreateDebug> Debug;
109
static ManagedStatic<cl::opt<unsigned>, CreateDebugBufferSize> DebugBufferSize;
110
111
namespace {
112
113
struct DebugOnlyOpt {
114
void operator=(const std::string &Val) const {
115
if (Val.empty())
116
return;
117
DebugFlag = true;
118
SmallVector<StringRef,8> dbgTypes;
119
StringRef(Val).split(dbgTypes, ',', -1, false);
120
for (auto dbgType : dbgTypes)
121
CurrentDebugType->push_back(std::string(dbgType));
122
}
123
};
124
} // namespace
125
126
static DebugOnlyOpt DebugOnlyOptLoc;
127
128
namespace {
129
struct CreateDebugOnly {
130
static void *call() {
131
return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>(
132
"debug-only",
133
cl::desc("Enable a specific type of debug output (comma separated list "
134
"of types)"),
135
cl::Hidden, cl::value_desc("debug string"),
136
cl::location(DebugOnlyOptLoc), cl::ValueRequired);
137
}
138
};
139
} // namespace
140
141
static ManagedStatic<cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>,
142
CreateDebugOnly>
143
DebugOnly;
144
145
void llvm::initDebugOptions() {
146
*Debug;
147
*DebugBufferSize;
148
*DebugOnly;
149
}
150
151
// Signal handlers - dump debug output on termination.
152
static void debug_user_sig_handler(void *Cookie) {
153
// This is a bit sneaky. Since this is under #ifndef NDEBUG, we
154
// know that debug mode is enabled and dbgs() really is a
155
// circular_raw_ostream. If NDEBUG is defined, then dbgs() ==
156
// errs() but this will never be invoked.
157
llvm::circular_raw_ostream &dbgout =
158
static_cast<circular_raw_ostream &>(llvm::dbgs());
159
dbgout.flushBufferWithBanner();
160
}
161
162
/// dbgs - Return a circular-buffered debug stream.
163
raw_ostream &llvm::dbgs() {
164
// Do one-time initialization in a thread-safe way.
165
static struct dbgstream {
166
circular_raw_ostream strm;
167
168
dbgstream()
169
: strm(errs(), "*** Debug Log Output ***\n",
170
(!EnableDebugBuffering || !DebugFlag) ? 0 : *DebugBufferSize) {
171
if (EnableDebugBuffering && DebugFlag && *DebugBufferSize != 0)
172
// TODO: Add a handler for SIGUSER1-type signals so the user can
173
// force a debug dump.
174
sys::AddSignalHandler(&debug_user_sig_handler, nullptr);
175
// Otherwise we've already set the debug stream buffer size to
176
// zero, disabling buffering so it will output directly to errs().
177
}
178
} thestrm;
179
180
return thestrm.strm;
181
}
182
183
#else
184
// Avoid "has no symbols" warning.
185
namespace llvm {
186
/// dbgs - Return errs().
187
raw_ostream &dbgs() {
188
return errs();
189
}
190
}
191
void llvm::initDebugOptions() {}
192
#endif
193
194
/// EnableDebugBuffering - Turn on signal handler installation.
195
///
196
bool llvm::EnableDebugBuffering = false;
197
198