19
19
namespace llvm {
20
20
#ifndef NDEBUG
21
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 somehow equivalent to
32
- // LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] " << __FILE__ << ":" <<
33
- // __LINE__ << " "
34
- // << "Bitset contains: " << Bitset << "\n");
35
- //
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 somehow equivalent to
32
+ // / LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] " << __FILE__ << ":" <<
33
+ // / __LINE__ << " "
34
+ // / << "Bitset contains: " << Bitset << "\n");
35
+ // /
36
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 a
44
- // macro that evaluates to a string.
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(2, "debug_type") << "Bitset contains: " << Bitset;
50
+ // / LDBG("debug_type", 2) << "Bitset contains: " << Bitset;
45
51
#define LDBG (...) _GET_LDBG_MACRO(__VA_ARGS__)(__VA_ARGS__)
46
52
47
- // Helper macros to choose the correct macro based on the number of arguments.
53
+ // / LDBG_OS() is a macro that behaves like LDBG() but instead of directly using
54
+ // / it to stream the output, it takes a callback function that will be called
55
+ // / with a raw_ostream.
56
+ // / This is useful when you need to pass a `raw_ostream` to a helper function to
57
+ // / be able to print (when the `<<` operator is not available).
58
+ // /
59
+ // / E.g.,
60
+ // / LDBG_OS([&] (raw_ostream &Os) {
61
+ // / Os << "Pass Manager contains: ";
62
+ // / pm.printAsTextual(Os);
63
+ // / });
64
+ // /
65
+ // / Just like LDBG(), it optionally accepts a `level` and `type` arguments.
66
+ // / E.g.,
67
+ // / LDBG_OS(2, [&] (raw_ostream &Os) { ... });
68
+ // / LDBG_OS("debug_type", [&] (raw_ostream &Os) { ... });
69
+ // / LDBG_OS(2, "debug_type", [&] (raw_ostream &Os) { ... });
70
+ // / LDBG_OS("debug_type", 2, [&] (raw_ostream &Os) { ... });
71
+ // /
72
+ #define LDBG_OS (...) _GET_LDBG_OS_MACRO(__VA_ARGS__)(__VA_ARGS__)
73
+
74
+ // Helper macros to choose the correct LDBG() macro based on the number of
75
+ // arguments.
48
76
#define LDBG_FUNC_CHOOSER (_f1, _f2, _f3, ...) _f3
49
77
#define LDBG_FUNC_RECOMPOSER (argsWithParentheses ) \
50
78
LDBG_FUNC_CHOOSER argsWithParentheses
51
79
#define LDBG_CHOOSE_FROM_ARG_COUNT (...) \
52
80
LDBG_FUNC_RECOMPOSER ( \
53
- (__VA_ARGS__, LDBG_LOG_LEVEL_WITH_TYPE, LDBG_LOG_LEVEL , ))
54
- #define LDBG_NO_ARG_EXPANDER () , , LDBG_LOG_LEVEL_1
81
+ (__VA_ARGS__, LDBG_LOG_LEVEL_WITH_TYPE, LDBG_LOG_LEVEL_1_ARG , ))
82
+ #define LDBG_NO_ARG_EXPANDER () , , LDBG_LOG_LEVEL_NO_ARG
55
83
#define _GET_LDBG_MACRO (...) \
56
84
LDBG_CHOOSE_FROM_ARG_COUNT (LDBG_NO_ARG_EXPANDER __VA_ARGS__ ())
57
85
58
- // Dispatch macros to support the `level` argument or none (default to 1)
59
- #define LDBG_LOG_LEVEL (LEVEL ) \
60
- DEBUGLOG_WITH_STREAM_AND_TYPE (llvm::dbgs(), LEVEL, DEBUG_TYPE)
61
- #define LDBG_LOG_LEVEL_1 () LDBG_LOG_LEVEL(1 )
62
- // This macro is a helper when LDBG() is called with 2 arguments.
63
- // In this case we want to allow the order of the arguments to be swapped.
64
- // We rely on the fact that the `level` argument is an integer, and the `type`
65
- // is a string and dispatch to a C++ API that is overloaded.
66
- #define LDBG_LOG_LEVEL_WITH_TYPE (LEVEL_OR_TYPE, TYPE_OR_LEVEL ) \
67
- DEBUGLOG_WITH_STREAM_AND_TYPE (llvm::dbgs(), (LEVEL_OR_TYPE), (TYPE_OR_LEVEL))
86
+ // Helper macros to choose the correct LDBG_OS() macro based on the number of
87
+ // arguments.
88
+ #define LDBG_OS_FUNC_CHOOSER (_f1, _f2, _f3, _f4, ...) _f4
89
+ #define LDBG_OS_FUNC_RECOMPOSER (argsWithParentheses ) \
90
+ LDBG_OS_FUNC_CHOOSER argsWithParentheses
91
+ #define LDBG_OS_CHOOSE_FROM_ARG_COUNT (...) \
92
+ LDBG_OS_FUNC_RECOMPOSER ( \
93
+ (__VA_ARGS__, LDBG_OS_3_ARGS, LDBG_OS_2_ARGS, LDBG_OS_1_ARG, ))
94
+ #define LDBG_OS_NO_ARG_EXPANDER () , , , LDBG_OS_1_ARG
95
+ #define _GET_LDBG_OS_MACRO (...) \
96
+ LDBG_OS_CHOOSE_FROM_ARG_COUNT (LDBG_OS_NO_ARG_EXPANDER __VA_ARGS__ ())
68
97
69
98
// We want the filename without the full path. We are using the __FILE__ macro
70
99
// and a constexpr function to strip the path prefix. We can avoid the frontend
@@ -76,29 +105,137 @@ namespace llvm {
76
105
#define __LLVM_FILE_NAME__ ::llvm::impl::getShortFileName (__FILE__)
77
106
#endif
78
107
79
- #define DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE (STREAM, LEVEL, TYPE, FILE, \
80
- LINE) \
81
- for (bool _c = \
82
- (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE, LEVEL)); \
108
+ // / These macros are detecting if the DEBUG_TYPE or LDBG_DEBUG_STREAM macros are
109
+ // / defined. They are using a combination of preprocessor tricks and C++17
110
+ // used-defined string literals to achieve this.
111
+ // For example, if DEBUG_TYPE is defined to "foo", the preprocessor will expand
112
+ // the macro and then stringify the result to
113
+ // "foo"_LDBG_VARIABLE_CHECK
114
+ // This dispatch to the user-defined string literal operator named
115
+ // _LDBG_VARIABLE_CHECK which returns true. Otherwise it expands to
116
+ // DEBUG_TYPE_LDBG_VARIABLE_CHECK which we define as a macro that returns false.
117
+ #define LDBG_VARIABLE_CHECK_ (VARIABLE, ...) VARIABLE##__VA_ARGS__
118
+ #define LDBG_VARIABLE_CHECK (VARIABLE ) \
119
+ LDBG_VARIABLE_CHECK_ (VARIABLE, _LDBG_VARIABLE_CHECK)
120
+ // User-defined string literal operator for the LDBG_VARIABLE_CHECK macro.
121
+ constexpr bool operator""_LDBG_VARIABLE_CHECK(const char *, std::size_t ) {
122
+ return true ;
123
+ }
124
+
125
+ #define IS_DEBUG_TYPE_DEFINED () LDBG_VARIABLE_CHECK(DEBUG_TYPE)
126
+ #define DEBUG_TYPE_LDBG_VARIABLE_CHECK 0
127
+
128
+ #define IS_LDBG_DEBUG_STREAM_DEFINED () LDBG_VARIABLE_CHECK(LDBG_DEBUG_STREAM)
129
+ #define LDBG_DEBUG_STREAM_LDBG_VARIABLE_CHECK 0
130
+
131
+ // / Helpers to get DEBUG_TYPE as a string literal, even when DEBUG_TYPE is not
132
+ // / defined (in which case it expand to "DEBUG_TYPE")
133
+ #define LDBG_GET_DEBUG_TYPE_STR__ (X ) #X##_LDBG_DEBUG_STRING
134
+ #define LDBG_GET_DEBUG_TYPE_STR_ (X ) LDBG_GET_DEBUG_TYPE_STR__(X)
135
+ #define LDBG_GET_DEBUG_TYPE_STR () LDBG_GET_DEBUG_TYPE_STR_(DEBUG_TYPE)
136
+ // / If DEBUG_TYPE is defined, we get the string with the quotes, we need to
137
+ // / remove them here.
138
+ constexpr ::llvm::StringRef operator " " _LDBG_DEBUG_STRING(const char *Str,
139
+ std::size_t ) {
140
+ ::llvm::StringRef S (Str);
141
+ if (S.front () == ' "' && S.back () == ' "' )
142
+ return S.drop_front ().drop_back ();
143
+ return S;
144
+ }
145
+
146
+ // / Helper to provide the default level (=1) or type (=DEBUG_TYPE). This is used
147
+ // / when a single argument is passed, if it is an integer we return DEBUG_TYPE
148
+ // / and if it is a string we return 1. This fails with a static_assert if we
149
+ // / pass an integer and DEBUG_TYPE is not defined.
150
+ #define LDBG_GET_DEFAULT_TYPE_OR_LEVEL (LEVEL_OR_TYPE ) \
151
+ [](auto LevelOrType) { \
152
+ if constexpr (std::is_integral_v<decltype (LevelOrType)>) { \
153
+ using ::llvm::operator " " _LDBG_VARIABLE_CHECK; \
154
+ using ::llvm::operator " " _LDBG_DEBUG_STRING; \
155
+ if constexpr (IS_DEBUG_TYPE_DEFINED ()) \
156
+ return LDBG_GET_DEBUG_TYPE_STR (); \
157
+ else \
158
+ static_assert (false , " DEBUG_TYPE is not defined" ); \
159
+ } else { \
160
+ return 1 ; \
161
+ } \
162
+ }(LEVEL_OR_TYPE)
163
+
164
+ // / Use a macro to allow unit-testing to override.
165
+ #define LDBG_STREAM ::llvm::dbgs ()
166
+
167
+ #define DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE (STREAM, LEVEL_OR_TYPE, \
168
+ TYPE_OR_LEVEL, FILE, LINE) \
169
+ for (bool _c = (::llvm::DebugFlag && ::llvm::impl::ldbgIsCurrentDebugType( \
170
+ TYPE_OR_LEVEL, LEVEL_OR_TYPE)); \
83
171
_c; _c = false ) \
84
172
for (::llvm::impl::raw_ldbg_ostream LdbgOS{ \
85
- ::llvm::impl::computePrefix (TYPE, FILE, LINE, LEVEL), (STREAM)}; \
173
+ ::llvm::impl::computePrefix (TYPE_OR_LEVEL, FILE, LINE, \
174
+ LEVEL_OR_TYPE), \
175
+ (STREAM), /* ShouldPrefixNextString=*/ true, \
176
+ /* ShouldEmitNewLineOnDestruction=*/ true}; \
86
177
_c; _c = false ) \
87
- ::llvm::impl::RAIINewLineStream{ LdbgOS}. asLvalue ()
178
+ LdbgOS
88
179
89
- #define DEBUGLOG_WITH_STREAM_TYPE_AND_FILE (STREAM, LEVEL, TYPE, FILE ) \
90
- DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE (STREAM, LEVEL, TYPE, FILE, __LINE__)
91
- #define DEBUGLOG_WITH_STREAM_AND_TYPE (STREAM, LEVEL, TYPE ) \
92
- DEBUGLOG_WITH_STREAM_TYPE_AND_FILE (STREAM, LEVEL, TYPE, __LLVM_FILE_NAME__)
180
+ #define DEBUGLOG_WITH_STREAM_TYPE_AND_FILE (STREAM, LEVEL_OR_TYPE, \
181
+ TYPE_OR_LEVEL, FILE) \
182
+ DEBUGLOG_WITH_STREAM_TYPE_FILE_AND_LINE (STREAM, LEVEL_OR_TYPE, \
183
+ TYPE_OR_LEVEL, FILE, __LINE__)
184
+ #define DEBUGLOG_WITH_STREAM_AND_TYPE (STREAM, LEVEL_OR_TYPE, TYPE_OR_LEVEL ) \
185
+ DEBUGLOG_WITH_STREAM_TYPE_AND_FILE (STREAM, LEVEL_OR_TYPE, TYPE_OR_LEVEL, \
186
+ __LLVM_FILE_NAME__)
187
+
188
+ // Dispatch macros when a signle argument is provided. This can be either a
189
+ // level of the debug type.
190
+ #define LDBG_LOG_LEVEL_1_ARG (LEVEL_OR_TYPE ) \
191
+ DEBUGLOG_WITH_STREAM_AND_TYPE (LDBG_STREAM, LEVEL_OR_TYPE, \
192
+ LDBG_GET_DEFAULT_TYPE_OR_LEVEL (LEVEL_OR_TYPE))
193
+ #define LDBG_LOG_LEVEL_NO_ARG () LDBG_LOG_LEVEL_1_ARG(1 )
194
+ // This macro is a helper when LDBG() is called with 2 arguments.
195
+ // In this case we want to allow the order of the arguments to be swapped.
196
+ // We rely on the fact that the `level` argument is an integer, and the `type`
197
+ // is a string and dispatch to a C++ API that is overloaded.
198
+ #define LDBG_LOG_LEVEL_WITH_TYPE (LEVEL_OR_TYPE, TYPE_OR_LEVEL ) \
199
+ DEBUGLOG_WITH_STREAM_AND_TYPE (LDBG_STREAM, (LEVEL_OR_TYPE), (TYPE_OR_LEVEL))
200
+
201
+ #define LDBG_OS_IMPL (TYPE_OR_LEVEL, LEVEL_OR_TYPE, CALLBACK, STREAM, FILE, \
202
+ LINE) \
203
+ if (::llvm::DebugFlag && \
204
+ ::llvm::impl::ldbgIsCurrentDebugType (TYPE_OR_LEVEL, LEVEL_OR_TYPE)) { \
205
+ ::llvm::impl::raw_ldbg_ostream LdbgOS{ \
206
+ ::llvm::impl::computePrefix (TYPE_OR_LEVEL, FILE, LINE, LEVEL_OR_TYPE), \
207
+ (STREAM), /* ShouldPrefixNextString=*/ true, \
208
+ /* ShouldEmitNewLineOnDestruction=*/ true}; \
209
+ CALLBACK (LdbgOS); \
210
+ }
211
+
212
+ #define LDBG_OS_3_ARGS (TYPE_OR_LEVEL, LEVEL_OR_TYPE, CALLBACK ) \
213
+ LDBG_OS_IMPL (TYPE_OR_LEVEL, LEVEL_OR_TYPE, CALLBACK, LDBG_STREAM, \
214
+ __LLVM_FILE_NAME__, __LINE__)
215
+
216
+ #define LDBG_OS_2_ARGS (LEVEL_OR_TYPE, CALLBACK ) \
217
+ LDBG_OS_3_ARGS (LDBG_GET_DEFAULT_TYPE_OR_LEVEL (LEVEL_OR_TYPE), LEVEL_OR_TYPE, \
218
+ CALLBACK)
219
+ #define LDBG_OS_1_ARG (CALLBACK ) LDBG_OS_2_ARGS(1 , CALLBACK)
93
220
94
221
namespace impl {
222
+ // / Helper to call isCurrentDebugType with a StringRef.
223
+ static LLVM_ATTRIBUTE_UNUSED bool ldbgIsCurrentDebugType (StringRef Type,
224
+ int Level) {
225
+ return ::llvm::isCurrentDebugType (Type.str ().c_str (), Level);
226
+ }
227
+ static LLVM_ATTRIBUTE_UNUSED bool ldbgIsCurrentDebugType (int Level,
228
+ StringRef Type) {
229
+ return ::llvm::isCurrentDebugType (Type.str ().c_str (), Level);
230
+ }
95
231
96
232
// / A raw_ostream that tracks `\n` and print the prefix after each
97
233
// / newline.
98
234
class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {
99
235
std::string Prefix;
100
236
raw_ostream &Os;
101
237
bool ShouldPrefixNextString;
238
+ bool ShouldEmitNewLineOnDestruction;
102
239
103
240
// / Split the line on newlines and insert the prefix before each
104
241
// / newline. Forward everything to the underlying stream.
@@ -131,12 +268,17 @@ class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {
131
268
132
269
public:
133
270
explicit raw_ldbg_ostream (std::string Prefix, raw_ostream &Os,
134
- bool ShouldPrefixNextString = true )
271
+ bool ShouldPrefixNextString = true ,
272
+ bool ShouldEmitNewLineOnDestruction = false )
135
273
: Prefix(std::move(Prefix)), Os(Os),
136
- ShouldPrefixNextString(ShouldPrefixNextString) {
274
+ ShouldPrefixNextString(ShouldPrefixNextString),
275
+ ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) {
137
276
SetUnbuffered ();
138
277
}
139
- ~raw_ldbg_ostream () final {}
278
+ ~raw_ldbg_ostream () final {
279
+ if (ShouldEmitNewLineOnDestruction)
280
+ Os << ' \n ' ;
281
+ }
140
282
141
283
// / Forward the current_pos method to the underlying stream.
142
284
uint64_t current_pos () const final { return Os.tell (); }
@@ -173,17 +315,17 @@ getShortFileName(const char *path) {
173
315
// / "[DebugType] File:Line "
174
316
// / Where the File is the file name without the path prefix.
175
317
static LLVM_ATTRIBUTE_UNUSED std::string
176
- computePrefix (const char * DebugType, const char *File, int Line, int Level) {
318
+ computePrefix (StringRef DebugType, const char *File, int Line, int Level) {
177
319
std::string Prefix;
178
320
raw_string_ostream OsPrefix (Prefix);
179
- if (DebugType)
321
+ if (! DebugType. empty () )
180
322
OsPrefix << " [" << DebugType << " :" << Level << " ] " ;
181
323
OsPrefix << File << " :" << Line << " " ;
182
324
return OsPrefix.str ();
183
325
}
184
326
// / Overload allowing to swap the order of the DebugType and Level arguments.
185
327
static LLVM_ATTRIBUTE_UNUSED std::string
186
- computePrefix (int Level, const char *File, int Line, const char * DebugType) {
328
+ computePrefix (int Level, const char *File, int Line, StringRef DebugType) {
187
329
return computePrefix (DebugType, File, Line, Level);
188
330
}
189
331
@@ -194,6 +336,7 @@ computePrefix(int Level, const char *File, int Line, const char *DebugType) {
194
336
#define LDBG (...) \
195
337
for (bool _c = false ; _c; _c = false ) \
196
338
::llvm::nulls ()
339
+ #define LDBG_OS (...)
197
340
#endif
198
341
} // end namespace llvm
199
342
0 commit comments