LLVM 22.0.0git
DebugLog.h
Go to the documentation of this file.
1//===- llvm/Support/DebugLog.h - Logging like debug output ------*- C++ -*-===//
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// This file contains macros for logging like debug output. It builds upon the
9// support in Debug.h but provides a utility function for common debug output
10// style.
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_SUPPORT_DEBUGLOG_H
14#define LLVM_SUPPORT_DEBUGLOG_H
15
16#include "llvm/Support/Debug.h"
18
19namespace llvm {
20#ifndef NDEBUG
21
22/// LDBG() is a macro that can be used as a raw_ostream for debugging.
23/// It will stream the output to the dbgs() stream, with a prefix of the
24/// debug type and the file and line number. A trailing newline is added to the
25/// output automatically. If the streamed content contains a newline, the prefix
26/// is added to each beginning of a new line. Nothing is printed if the debug
27/// output is not enabled or the debug type does not match.
28///
29/// E.g.,
30/// LDBG() << "Bitset contains: " << Bitset;
31/// is equivalent to
32/// LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] " << __FILE__ << ":" <<
33/// __LINE__ << " "
34/// << "Bitset contains: " << Bitset << "\n");
35///
36// An optional `level` argument can be provided to control the verbosity of the
37/// output. The default level is 1, and is in increasing level of verbosity.
38///
39/// The `level` argument can be a literal integer, or a macro that evaluates to
40/// an integer.
41///
42/// An optional `type` argument can be provided to control the debug type. The
43/// default type is DEBUG_TYPE. The `type` argument can be a literal string, or
44/// a macro that evaluates to a string.
45///
46/// E.g.,
47/// LDBG(2) << "Bitset contains: " << Bitset;
48/// LDBG("debug_type") << "Bitset contains: " << Bitset;
49/// LDBG("debug_type", 2) << "Bitset contains: " << Bitset;
50#define LDBG(...) _GET_LDBG_MACRO(__VA_ARGS__)(__VA_ARGS__)
51
52/// LDBG_OS() is a macro that behaves like LDBG() but instead of directly using
53/// it to stream the output, it takes a callback function that will be called
54/// with a raw_ostream.
55/// This is useful when you need to pass a `raw_ostream` to a helper function to
56/// be able to print (when the `<<` operator is not available).
57///
58/// E.g.,
59/// LDBG_OS([&] (raw_ostream &Os) {
60/// Os << "Pass Manager contains: ";
61/// pm.printAsTextual(Os);
62/// });
63///
64/// Just like LDBG(), it optionally accepts a `level` and `type` arguments.
65/// E.g.,
66/// LDBG_OS(2, [&] (raw_ostream &Os) { ... });
67/// LDBG_OS("debug_type", [&] (raw_ostream &Os) { ... });
68/// LDBG_OS("debug_type", 2, [&] (raw_ostream &Os) { ... });
69///
70#define LDBG_OS(...) _GET_LDBG_OS_MACRO(__VA_ARGS__)(__VA_ARGS__)
71
72// We want the filename without the full path. We are using the __FILE__ macro
73// and a constexpr function to strip the path prefix. We can avoid the frontend
74// repeated evaluation of __FILE__ by using the __FILE_NAME__ when defined
75// (gcc and clang do) which contains the file name already.
76#if defined(__FILE_NAME__)
77#define __LLVM_FILE_NAME__ __FILE_NAME__
78#else
79#define __LLVM_FILE_NAME__ ::llvm::impl::getShortFileName(__FILE__)
80#endif
81
82// Everything below are implementation details of the macros above.
83namespace impl {
84
85/// This macro expands to the stream to use for output, we use a macro to allow
86/// unit-testing to override.
87#define LDBG_STREAM ::llvm::dbgs()
88
89// ----------------------------------------------------------------------------
90// LDBG() implementation
91// ----------------------------------------------------------------------------
92
93// Helper macros to choose the correct LDBG() macro based on the number of
94// arguments.
95#define LDBG_FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
96#define LDBG_FUNC_RECOMPOSER(argsWithParentheses) \
97 LDBG_FUNC_CHOOSER argsWithParentheses
98#define LDBG_CHOOSE_FROM_ARG_COUNT(...) \
99 LDBG_FUNC_RECOMPOSER((__VA_ARGS__, LDBG_TYPE_AND_LEVEL, LDBG_LEVEL_OR_TYPE, ))
100#define LDBG_NO_ARG_EXPANDER() , , LDBG_NO_ARG
101#define _GET_LDBG_MACRO(...) \
102 LDBG_CHOOSE_FROM_ARG_COUNT(LDBG_NO_ARG_EXPANDER __VA_ARGS__())
103
104/// This macro is the core of the LDBG() implementation. It is used to print the
105/// debug output with the given stream, level, type, file, and line number.
106#define LDBG_STREAM_LEVEL_TYPE_FILE_AND_LINE(STREAM, LEVEL_OR_TYPE, \
107 TYPE_OR_LEVEL, FILE, LINE) \
108 for (bool _c = ::llvm::DebugFlag && ::llvm::impl::ldbgIsCurrentDebugType( \
109 TYPE_OR_LEVEL, LEVEL_OR_TYPE); \
110 _c; _c = false) \
111 ::llvm::impl::raw_ldbg_ostream{ \
112 ::llvm::impl::computePrefix(TYPE_OR_LEVEL, FILE, LINE, LEVEL_OR_TYPE), \
113 (STREAM), /*ShouldPrefixNextString=*/true, \
114 /*ShouldEmitNewLineOnDestruction=*/true} \
115 .asLvalue()
116
117/// These macros are helpers to implement LDBG() with an increasing amount of
118/// optional arguments made explicit.
119#define LDBG_STREAM_LEVEL_TYPE_AND_FILE(STREAM, LEVEL_OR_TYPE, TYPE_OR_LEVEL, \
120 FILE) \
121 LDBG_STREAM_LEVEL_TYPE_FILE_AND_LINE(STREAM, LEVEL_OR_TYPE, TYPE_OR_LEVEL, \
122 FILE, __LINE__)
123#define LDGB_STREAM_LEVEL_AND_TYPE(STREAM, LEVEL_OR_TYPE, TYPE_OR_LEVEL) \
124 LDBG_STREAM_LEVEL_TYPE_AND_FILE(STREAM, LEVEL_OR_TYPE, TYPE_OR_LEVEL, \
125 __LLVM_FILE_NAME__)
126/// This macro is a helper when LDBG() is called with 2 arguments.
127/// In this case we want to force the first argument to be the type for
128/// consistency in the codebase.
129/// We trick this by casting the first argument to a (const char *) which
130/// won't compile with an int.
131#define LDBG_TYPE_AND_LEVEL(TYPE, LEVEL) \
132 LDGB_STREAM_LEVEL_AND_TYPE(LDBG_STREAM, static_cast<const char *>(TYPE), \
133 (LEVEL))
134
135/// When a single argument is provided. This can be either a level or the debug
136/// type. If a level is provided, we default the debug type to DEBUG_TYPE, if a
137/// string is provided, we default the level to 1.
138#define LDBG_LEVEL_OR_TYPE(LEVEL_OR_TYPE) \
139 LDGB_STREAM_LEVEL_AND_TYPE(LDBG_STREAM, (LEVEL_OR_TYPE), \
140 LDBG_GET_DEFAULT_TYPE_OR_LEVEL(LEVEL_OR_TYPE))
141#define LDBG_NO_ARG() LDBG_LEVEL_OR_TYPE(1)
142
143// ----------------------------------------------------------------------------
144// LDBG_OS() implementation
145// ----------------------------------------------------------------------------
146
147// Helper macros to choose the correct LDBG_OS() macro based on the number of
148// arguments.
149#define LDBG_OS_FUNC_CHOOSER(_f1, _f2, _f3, _f4, ...) _f4
150#define LDBG_OS_FUNC_RECOMPOSER(argsWithParentheses) \
151 LDBG_OS_FUNC_CHOOSER argsWithParentheses
152#define LDBG_OS_CHOOSE_FROM_ARG_COUNT(...) \
153 LDBG_OS_FUNC_RECOMPOSER((__VA_ARGS__, LDBG_OS_TYPE_AND_LEVEL_AND_CALLBACK, \
154 LDBG_OS_LEVEL_OR_TYPE_AND_CALLBACK, \
155 LDBG_OS_CALLBACK, ))
156#define LDBG_OS_NO_ARG_EXPANDER() , , , LDBG_OS_CALLBACK
157#define _GET_LDBG_OS_MACRO(...) \
158 LDBG_OS_CHOOSE_FROM_ARG_COUNT(LDBG_OS_NO_ARG_EXPANDER __VA_ARGS__())
159
160/// This macro is the core of the LDBG_OS() macros. It is used to print the
161/// debug output with the given stream, level, type, file, and line number.
162#define LDBG_OS_IMPL(TYPE_OR_LEVEL, LEVEL_OR_TYPE, CALLBACK, STREAM, FILE, \
163 LINE) \
164 if (::llvm::DebugFlag && \
165 ::llvm::impl::ldbgIsCurrentDebugType(TYPE_OR_LEVEL, LEVEL_OR_TYPE)) { \
166 ::llvm::impl::raw_ldbg_ostream LdbgOS{ \
167 ::llvm::impl::computePrefix(TYPE_OR_LEVEL, FILE, LINE, LEVEL_OR_TYPE), \
168 (STREAM), /*ShouldPrefixNextString=*/true, \
169 /*ShouldEmitNewLineOnDestruction=*/true}; \
170 CALLBACK(LdbgOS); \
171 }
172
173#define LDBG_OS_TYPE_AND_LEVEL_AND_CALLBACK(TYPE, LEVEL, CALLBACK) \
174 LDBG_OS_IMPL(static_cast<const char *>(TYPE), LEVEL, CALLBACK, LDBG_STREAM, \
175 __LLVM_FILE_NAME__, __LINE__)
176#define LDBG_OS_LEVEL_OR_TYPE_AND_CALLBACK(LEVEL_OR_TYPE, CALLBACK) \
177 LDBG_OS_IMPL(LDBG_GET_DEFAULT_TYPE_OR_LEVEL(LEVEL_OR_TYPE), LEVEL_OR_TYPE, \
178 CALLBACK, LDBG_STREAM, __LLVM_FILE_NAME__, __LINE__)
179#define LDBG_OS_CALLBACK(CALLBACK) \
180 LDBG_OS_LEVEL_OR_TYPE_AND_CALLBACK(1, CALLBACK)
181
182// ----------------------------------------------------------------------------
183// General Helpers for the implementation above
184// ----------------------------------------------------------------------------
185
186/// Return the stringified macro as a StringRef.
187/// Also, strip out potential surrounding quotes: this comes from an artifact of
188/// the macro stringification, if DEBUG_TYPE is undefined we get the string
189/// "DEBUG_TYPE", however if it is defined we get the string with the quotes.
190/// For example if DEBUG_TYPE is "foo", we get "\"foo\"" but we want to return
191/// "foo" here.
192constexpr ::llvm::StringRef strip_quotes(const char *Str) {
193 ::llvm::StringRef S(Str);
194 if (Str[0] == '"' && Str[S.size() - 1] == '"')
195 return StringRef(Str + 1, S.size() - 2);
196 return S;
197}
198
199/// Fail compilation if DEBUG_TYPE is not defined.
200/// This is a workaround for GCC <=12 and clang <=16 which do not support
201/// static_assert in templated constexpr functions.
202#if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 12) || \
203 (defined(__clang__) && __clang_major__ <= 16)
204#define MISSING_DEBUG_TYPE() \
205 extern void missing_DEBUG_TYPE(void); \
206 missing_DEBUG_TYPE();
207#else
208#define MISSING_DEBUG_TYPE() static_assert(false, "DEBUG_TYPE is not defined");
209#endif
210
211/// Helper to provide the default level (=1) or type (=DEBUG_TYPE). This is used
212/// when a single argument is passed to LDBG() (or LDBG_OS()), if it is an
213/// integer we return DEBUG_TYPE and if it is a string we return 1. This fails
214/// with a static_assert if we pass an integer and DEBUG_TYPE is not defined.
215#define LDBG_GET_DEFAULT_TYPE_OR_LEVEL(LEVEL_OR_TYPE) \
216 [](auto LevelOrType) { \
217 if constexpr (std::is_integral_v<decltype(LevelOrType)>) { \
218 constexpr const char *DebugType = LDBG_GET_DEBUG_TYPE_STR(); \
219 if constexpr (DebugType[0] == '"') { \
220 return ::llvm::impl::strip_quotes(DebugType); \
221 } else { \
222 MISSING_DEBUG_TYPE(); \
223 } \
224 } else { \
225 return 1; \
226 } \
227 }(LEVEL_OR_TYPE)
228
229/// Helpers to get DEBUG_TYPE as a StringRef, even when DEBUG_TYPE is not
230/// defined (in which case it expands to "DEBUG_TYPE")
231#define LDBG_GET_DEBUG_TYPE_STR__(X) #X
232#define LDBG_GET_DEBUG_TYPE_STR_(X) LDBG_GET_DEBUG_TYPE_STR__(X)
233#define LDBG_GET_DEBUG_TYPE_STR() LDBG_GET_DEBUG_TYPE_STR_(DEBUG_TYPE)
234
235/// Helper to call isCurrentDebugType with a StringRef.
236static LLVM_ATTRIBUTE_UNUSED bool ldbgIsCurrentDebugType(StringRef Type,
237 int Level) {
238 return ::llvm::isCurrentDebugType(Type.str().c_str(), Level);
239}
240static LLVM_ATTRIBUTE_UNUSED bool ldbgIsCurrentDebugType(int Level,
241 StringRef Type) {
242 return ::llvm::isCurrentDebugType(Type.str().c_str(), Level);
243}
244
245/// A raw_ostream that tracks `\n` and print the prefix after each
246/// newline.
247class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {
248 std::string Prefix;
249 raw_ostream &Os;
250 bool ShouldPrefixNextString;
251 bool ShouldEmitNewLineOnDestruction;
252
253 /// Split the line on newlines and insert the prefix before each
254 /// newline. Forward everything to the underlying stream.
255 void write_impl(const char *Ptr, size_t Size) final {
256 auto Str = StringRef(Ptr, Size);
257 auto Eol = Str.find('\n');
258 // Handle `\n` occurring in the string, ensure to print the prefix at the
259 // beginning of each line.
260 while (Eol != StringRef::npos) {
261 // Take the line up to the newline (including the newline).
262 StringRef Line = Str.take_front(Eol + 1);
263 if (!Line.empty())
264 writeWithPrefix(Line);
265 // We printed a newline, record here to print a prefix.
266 ShouldPrefixNextString = true;
267 Str = Str.drop_front(Eol + 1);
268 Eol = Str.find('\n');
269 }
270 if (!Str.empty())
271 writeWithPrefix(Str);
272 }
273 void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); }
274 void writeWithPrefix(StringRef Str) {
275 if (ShouldPrefixNextString) {
276 emitPrefix();
277 ShouldPrefixNextString = false;
278 }
279 Os.write(Str.data(), Str.size());
280 }
281
282public:
283 explicit raw_ldbg_ostream(std::string Prefix, raw_ostream &Os,
284 bool ShouldPrefixNextString = true,
285 bool ShouldEmitNewLineOnDestruction = false)
286 : Prefix(std::move(Prefix)), Os(Os),
287 ShouldPrefixNextString(ShouldPrefixNextString),
288 ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) {
289 SetUnbuffered();
290 }
291 ~raw_ldbg_ostream() final {
292 if (ShouldEmitNewLineOnDestruction)
293 Os << '\n';
294 }
295
296 /// Forward the current_pos method to the underlying stream.
297 uint64_t current_pos() const final { return Os.tell(); }
298
299 /// Some of the `<<` operators expect an lvalue, so we trick the type
300 /// system.
301 raw_ldbg_ostream &asLvalue() { return *this; }
302};
303
304/// A raw_ostream that prints a newline on destruction, useful for LDBG()
305class RAIINewLineStream final : public raw_ostream {
306 raw_ostream &Os;
307
308public:
309 RAIINewLineStream(raw_ostream &Os) : Os(Os) { SetUnbuffered(); }
310 ~RAIINewLineStream() { Os << '\n'; }
311 void write_impl(const char *Ptr, size_t Size) final { Os.write(Ptr, Size); }
312 uint64_t current_pos() const final { return Os.tell(); }
313 RAIINewLineStream &asLvalue() { return *this; }
314};
315
316/// Remove the path prefix from the file name.
317static LLVM_ATTRIBUTE_UNUSED constexpr const char *
318getShortFileName(const char *path) {
319 const char *filename = path;
320 for (const char *p = path; *p != '\0'; ++p) {
321 if (*p == '/' || *p == '\\')
322 filename = p + 1;
323 }
324 return filename;
325}
326
327/// Compute the prefix for the debug log in the form of:
328/// "[DebugType] File:Line "
329/// Where the File is the file name without the path prefix.
330static LLVM_ATTRIBUTE_UNUSED std::string
331computePrefix(StringRef DebugType, const char *File, int Line, int Level) {
332 std::string Prefix;
333 raw_string_ostream OsPrefix(Prefix);
334 if (!DebugType.empty())
335 OsPrefix << "[" << DebugType << ":" << Level << "] ";
336 OsPrefix << File << ":" << Line << " ";
337 return OsPrefix.str();
338}
339/// Overload allowing to swap the order of the DebugType and Level arguments.
340static LLVM_ATTRIBUTE_UNUSED std::string
341computePrefix(int Level, const char *File, int Line, StringRef DebugType) {
342 return computePrefix(DebugType, File, Line, Level);
343}
344
345} // end namespace impl
346#else
347// As others in Debug, When compiling without assertions, the -debug-* options
348// and all inputs too LDBG() are ignored.
349#define LDBG(...) \
350 for (bool _c = false; _c; _c = false) \
351 ::llvm::nulls()
352#define LDBG_OS(...)
353#endif
354} // end namespace llvm
355
356#endif // LLVM_SUPPORT_DEBUGLOG_H
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:154
constexpr ::llvm::StringRef strip_quotes(const char *Str)
Return the stringified macro as a StringRef.
Definition DebugLog.h:192
This is an optimization pass for GlobalISel generic memory operations.