1919namespace llvm {
2020#ifndef NDEBUG
2121
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 equivalent to
32+ // / LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] " << __FILE__ << ":" <<
33+ // / __LINE__ << " "
34+ // / << "Bitset contains: " << Bitset << "\n");
35+ // /
3636// 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("debug_type", 2) << "Bitset contains: " << Bitset;
4550#define LDBG (...) _GET_LDBG_MACRO(__VA_ARGS__)(__VA_ARGS__)
4651
47- // Helper macros to choose the correct macro based on the number of arguments.
48- #define LDBG_FUNC_CHOOSER (_f1, _f2, _f3, ...) _f3
49- #define LDBG_FUNC_RECOMPOSER (argsWithParentheses ) \
50- LDBG_FUNC_CHOOSER argsWithParentheses
51- #define LDBG_CHOOSE_FROM_ARG_COUNT (...) \
52- LDBG_FUNC_RECOMPOSER ( \
53- (__VA_ARGS__, LDBG_LOG_LEVEL_WITH_TYPE, LDBG_LOG_LEVEL, ))
54- #define LDBG_NO_ARG_EXPANDER () , , LDBG_LOG_LEVEL_1
55- #define _GET_LDBG_MACRO (...) \
56- LDBG_CHOOSE_FROM_ARG_COUNT (LDBG_NO_ARG_EXPANDER __VA_ARGS__ ())
57-
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))
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__)
6871
6972// We want the filename without the full path. We are using the __FILE__ macro
7073// and a constexpr function to strip the path prefix. We can avoid the frontend
@@ -76,29 +79,175 @@ namespace llvm {
7679#define __LLVM_FILE_NAME__ ::llvm::impl::getShortFileName (__FILE__)
7780#endif
7881
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)); \
82+ // Everything below are implementation details of the macros above.
83+ namespace 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); \
83110 _c; _c = false ) \
84- for (::llvm::impl::raw_ldbg_ostream LdbgOS{ \
85- ::llvm::impl::computePrefix (TYPE, FILE, LINE, LEVEL), (STREAM)}; \
86- _c; _c = false ) \
87- ::llvm::impl::RAIINewLineStream{LdbgOS}.asLvalue ()
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 ()
88116
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__)
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))
93134
94- namespace impl {
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.
192+ constexpr ::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 which does not support static_assert in
201+ // / templated constexpr functions.
202+ #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 12
203+ #define MISSING_DEBUG_TYPE () \
204+ extern void missing_DEBUG_TYPE (void ); \
205+ missing_DEBUG_TYPE ();
206+ #else
207+ #define MISSING_DEBUG_TYPE () static_assert (false , " DEBUG_TYPE is not defined" );
208+ #endif
209+
210+ // / Helper to provide the default level (=1) or type (=DEBUG_TYPE). This is used
211+ // / when a single argument is passed to LDBG() (or LDBG_OS()), if it is an
212+ // / integer we return DEBUG_TYPE and if it is a string we return 1. This fails
213+ // / with a static_assert if we pass an integer and DEBUG_TYPE is not defined.
214+ #define LDBG_GET_DEFAULT_TYPE_OR_LEVEL (LEVEL_OR_TYPE ) \
215+ [](auto LevelOrType) { \
216+ if constexpr (std::is_integral_v<decltype (LevelOrType)>) { \
217+ constexpr const char *DebugType = LDBG_GET_DEBUG_TYPE_STR (); \
218+ if constexpr (DebugType[0 ] == ' "' ) { \
219+ return ::llvm::impl::strip_quotes (DebugType); \
220+ } else { \
221+ MISSING_DEBUG_TYPE (); \
222+ } \
223+ } else { \
224+ return 1 ; \
225+ } \
226+ }(LEVEL_OR_TYPE)
227+
228+ // / Helpers to get DEBUG_TYPE as a StringRef, even when DEBUG_TYPE is not
229+ // / defined (in which case it expands to "DEBUG_TYPE")
230+ #define LDBG_GET_DEBUG_TYPE_STR__ (X ) #X
231+ #define LDBG_GET_DEBUG_TYPE_STR_ (X ) LDBG_GET_DEBUG_TYPE_STR__(X)
232+ #define LDBG_GET_DEBUG_TYPE_STR () LDBG_GET_DEBUG_TYPE_STR_(DEBUG_TYPE)
233+
234+ // / Helper to call isCurrentDebugType with a StringRef.
235+ static LLVM_ATTRIBUTE_UNUSED bool ldbgIsCurrentDebugType (StringRef Type,
236+ int Level) {
237+ return ::llvm::isCurrentDebugType (Type.str ().c_str (), Level);
238+ }
239+ static LLVM_ATTRIBUTE_UNUSED bool ldbgIsCurrentDebugType (int Level,
240+ StringRef Type) {
241+ return ::llvm::isCurrentDebugType (Type.str ().c_str (), Level);
242+ }
95243
96244// / A raw_ostream that tracks `\n` and print the prefix after each
97245// / newline.
98246class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {
99247 std::string Prefix;
100248 raw_ostream &Os;
101249 bool ShouldPrefixNextString;
250+ bool ShouldEmitNewLineOnDestruction;
102251
103252 // / Split the line on newlines and insert the prefix before each
104253 // / newline. Forward everything to the underlying stream.
@@ -131,12 +280,17 @@ class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {
131280
132281public:
133282 explicit raw_ldbg_ostream (std::string Prefix, raw_ostream &Os,
134- bool ShouldPrefixNextString = true )
283+ bool ShouldPrefixNextString = true ,
284+ bool ShouldEmitNewLineOnDestruction = false )
135285 : Prefix(std::move(Prefix)), Os(Os),
136- ShouldPrefixNextString(ShouldPrefixNextString) {
286+ ShouldPrefixNextString(ShouldPrefixNextString),
287+ ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) {
137288 SetUnbuffered ();
138289 }
139- ~raw_ldbg_ostream () final {}
290+ ~raw_ldbg_ostream () final {
291+ if (ShouldEmitNewLineOnDestruction)
292+ Os << ' \n ' ;
293+ }
140294
141295 // / Forward the current_pos method to the underlying stream.
142296 uint64_t current_pos () const final { return Os.tell (); }
@@ -173,17 +327,17 @@ getShortFileName(const char *path) {
173327// / "[DebugType] File:Line "
174328// / Where the File is the file name without the path prefix.
175329static LLVM_ATTRIBUTE_UNUSED std::string
176- computePrefix (const char * DebugType, const char *File, int Line, int Level) {
330+ computePrefix (StringRef DebugType, const char *File, int Line, int Level) {
177331 std::string Prefix;
178332 raw_string_ostream OsPrefix (Prefix);
179- if (DebugType)
333+ if (! DebugType. empty () )
180334 OsPrefix << " [" << DebugType << " :" << Level << " ] " ;
181335 OsPrefix << File << " :" << Line << " " ;
182336 return OsPrefix.str ();
183337}
184338// / Overload allowing to swap the order of the DebugType and Level arguments.
185339static LLVM_ATTRIBUTE_UNUSED std::string
186- computePrefix (int Level, const char *File, int Line, const char * DebugType) {
340+ computePrefix (int Level, const char *File, int Line, StringRef DebugType) {
187341 return computePrefix (DebugType, File, Line, Level);
188342}
189343
@@ -194,6 +348,7 @@ computePrefix(int Level, const char *File, int Line, const char *DebugType) {
194348#define LDBG (...) \
195349 for (bool _c = false ; _c; _c = false ) \
196350 ::llvm::nulls ()
351+ #define LDBG_OS (...)
197352#endif
198353} // end namespace llvm
199354
0 commit comments