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 somehow 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 a
44// macro that evaluates to a string.
45#define LDBG(...) _GET_LDBG_MACRO(__VA_ARGS__)(__VA_ARGS__)
46
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))
68
69// We want the filename without the full path. We are using the __FILE__ macro
70// and a constexpr function to strip the path prefix. We can avoid the frontend
71// repeated evaluation of __FILE__ by using the __FILE_NAME__ when defined
72// (gcc and clang do) which contains the file name already.
73#if defined(__FILE_NAME__)
74#define __LLVM_FILE_NAME__ __FILE_NAME__
75#else
76#define __LLVM_FILE_NAME__ ::llvm::impl::getShortFileName(__FILE__)
77#endif
78
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)); \
83 _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()
88
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__)
93
94namespace impl {
95
96/// A raw_ostream that tracks `\n` and print the prefix after each
97/// newline.
99 std::string Prefix;
100 raw_ostream &Os;
101 bool ShouldPrefixNextString;
102
103 /// Split the line on newlines and insert the prefix before each
104 /// newline. Forward everything to the underlying stream.
105 void write_impl(const char *Ptr, size_t Size) final {
106 auto Str = StringRef(Ptr, Size);
107 auto Eol = Str.find('\n');
108 // Handle `\n` occurring in the string, ensure to print the prefix at the
109 // beginning of each line.
110 while (Eol != StringRef::npos) {
111 // Take the line up to the newline (including the newline).
112 StringRef Line = Str.take_front(Eol + 1);
113 if (!Line.empty())
114 writeWithPrefix(Line);
115 // We printed a newline, record here to print a prefix.
116 ShouldPrefixNextString = true;
117 Str = Str.drop_front(Eol + 1);
118 Eol = Str.find('\n');
119 }
120 if (!Str.empty())
121 writeWithPrefix(Str);
122 }
123 void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); }
124 void writeWithPrefix(StringRef Str) {
125 if (ShouldPrefixNextString) {
126 emitPrefix();
127 ShouldPrefixNextString = false;
128 }
129 Os.write(Str.data(), Str.size());
130 }
131
132public:
133 explicit raw_ldbg_ostream(std::string Prefix, raw_ostream &Os,
134 bool ShouldPrefixNextString = true)
135 : Prefix(std::move(Prefix)), Os(Os),
136 ShouldPrefixNextString(ShouldPrefixNextString) {
137 SetUnbuffered();
138 }
140
141 /// Forward the current_pos method to the underlying stream.
142 uint64_t current_pos() const final { return Os.tell(); }
143
144 /// Some of the `<<` operators expect an lvalue, so we trick the type
145 /// system.
146 raw_ldbg_ostream &asLvalue() { return *this; }
147};
148
149/// A raw_ostream that prints a newline on destruction, useful for LDBG()
150class RAIINewLineStream final : public raw_ostream {
151 raw_ostream &Os;
152
153public:
155 ~RAIINewLineStream() { Os << '\n'; }
156 void write_impl(const char *Ptr, size_t Size) final { Os.write(Ptr, Size); }
157 uint64_t current_pos() const final { return Os.tell(); }
158 RAIINewLineStream &asLvalue() { return *this; }
159};
160
161/// Remove the path prefix from the file name.
162static LLVM_ATTRIBUTE_UNUSED constexpr const char *
163getShortFileName(const char *path) {
164 const char *filename = path;
165 for (const char *p = path; *p != '\0'; ++p) {
166 if (*p == '/' || *p == '\\')
167 filename = p + 1;
168 }
169 return filename;
170}
171
172/// Compute the prefix for the debug log in the form of:
173/// "[DebugType] File:Line "
174/// Where the File is the file name without the path prefix.
175static LLVM_ATTRIBUTE_UNUSED std::string
176computePrefix(const char *DebugType, const char *File, int Line, int Level) {
177 std::string Prefix;
178 raw_string_ostream OsPrefix(Prefix);
179 if (DebugType)
180 OsPrefix << "[" << DebugType << ":" << Level << "] ";
181 OsPrefix << File << ":" << Line << " ";
182 return OsPrefix.str();
183}
184/// Overload allowing to swap the order of the DebugType and Level arguments.
185static LLVM_ATTRIBUTE_UNUSED std::string
186computePrefix(int Level, const char *File, int Line, const char *DebugType) {
187 return computePrefix(DebugType, File, Line, Level);
188}
189
190} // end namespace impl
191#else
192// As others in Debug, When compiling without assertions, the -debug-* options
193// and all inputs too LDBG() are ignored.
194#define LDBG(...) \
195 for (bool _c = false; _c; _c = false) \
196 ::llvm::nulls()
197#endif
198} // end namespace llvm
199
200#endif // LLVM_SUPPORT_DEBUGLOG_H
aarch64 promote const
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:298
uint64_t Size
place backedge safepoints impl
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
A raw_ostream that prints a newline on destruction, useful for LDBG()
Definition: DebugLog.h:150
void write_impl(const char *Ptr, size_t Size) final
The is the piece of the class that is implemented by subclasses.
Definition: DebugLog.h:156
RAIINewLineStream & asLvalue()
Definition: DebugLog.h:158
uint64_t current_pos() const final
Return the current position within the stream, not counting the bytes currently in the buffer.
Definition: DebugLog.h:157
RAIINewLineStream(raw_ostream &Os)
Definition: DebugLog.h:154
A raw_ostream that tracks \n and print the prefix after each newline.
Definition: DebugLog.h:98
raw_ldbg_ostream(std::string Prefix, raw_ostream &Os, bool ShouldPrefixNextString=true)
Definition: DebugLog.h:133
raw_ldbg_ostream & asLvalue()
Some of the << operators expect an lvalue, so we trick the type system.
Definition: DebugLog.h:146
uint64_t current_pos() const final
Forward the current_pos method to the underlying stream.
Definition: DebugLog.h:142
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:148
raw_ostream & write(unsigned char C)
void SetUnbuffered()
Set the stream to be unbuffered.
Definition: raw_ostream.h:186
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:662
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:680
static LLVM_ATTRIBUTE_UNUSED constexpr const char * getShortFileName(const char *path)
Remove the path prefix from the file name.
Definition: DebugLog.h:163
static LLVM_ATTRIBUTE_UNUSED std::string computePrefix(const char *DebugType, const char *File, int Line, int Level)
Compute the prefix for the debug log in the form of: "[DebugType] File:Line " Where the File is the f...
Definition: DebugLog.h:176
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856