@@ -26,55 +26,107 @@ namespace llvm {
26
26
// << "] " << "Bitset contains: " << Bitset << "\n");
27
27
#define LDBG () DEBUGLOG_WITH_STREAM_AND_TYPE(llvm::dbgs(), DEBUG_TYPE)
28
28
29
- #if defined(__SHORT_FILE__)
30
- #define DEBUGLOG_WITH_STREAM_AND_TYPE (STREAM, TYPE ) \
29
+ #define DEBUGLOG_WITH_STREAM_TYPE_AND_FILE (STREAM, TYPE, FILE ) \
31
30
for (bool _c = (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)); _c; \
32
31
_c = false ) \
33
- ::llvm::impl::LogWithNewline (TYPE, __SHORT_FILE__, __LINE__, (STREAM))
32
+ ::llvm::impl::raw_ldbg_ostream{ \
33
+ ::llvm::impl::computePrefix (TYPE, FILE, __LINE__), (STREAM)} \
34
+ .asLvalue ()
35
+ // When __SHORT_FILE__ is not defined, the File is the full path,
36
+ // otherwise __SHORT_FILE__ is defined in CMake to provide the file name
37
+ // without the path prefix.
38
+ #if defined(__SHORT_FILE__)
39
+ #define DEBUGLOG_WITH_STREAM_AND_TYPE (STREAM, TYPE ) \
40
+ DEBUGLOG_WITH_STREAM_TYPE_AND_FILE (STREAM, TYPE, __SHORT_FILE__)
34
41
#else
35
42
#define DEBUGLOG_WITH_STREAM_AND_TYPE (STREAM, TYPE ) \
36
- for (bool _c = (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)); _c; \
37
- _c = false ) \
38
- ::llvm::impl::LogWithNewline (TYPE, __FILE__, __LINE__, (STREAM))
43
+ DEBUGLOG_WITH_STREAM_TYPE_AND_FILE ( \
44
+ STREAM, TYPE, ::llvm::impl::LogWithNewline::getShortFileName (__FILE__))
39
45
#endif
40
46
41
47
namespace impl {
42
- class LogWithNewline {
43
- public:
44
- LogWithNewline (const char *debug_type, const char *file, int line,
45
- raw_ostream &os)
46
- : os(os) {
47
- #if !defined(__SHORT_FILE__)
48
- file = ::llvm::impl::LogWithNewline::getShortFileName (file);
49
- #endif
50
- if (debug_type)
51
- os << " [" << debug_type << " ] " ;
52
- os << file << " :" << line << " " ;
48
+
49
+ // / A raw_ostream that tracks `\n` and print the prefix.
50
+ class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {
51
+ std::string Prefix;
52
+ raw_ostream &Os;
53
+ bool HasPendingNewline = true ;
54
+
55
+ // / Split the line on newlines and insert the prefix before each newline.
56
+ // / Forward everything to the underlying stream.
57
+ void write_impl (const char *Ptr, size_t Size) final {
58
+ auto Str = StringRef (Ptr, Size);
59
+ // Handle the initial prefix.
60
+ if (!Str.empty ())
61
+ writeWithPrefix (StringRef ());
62
+
63
+ auto Eol = Str.find (' \n ' );
64
+ while (Eol != StringRef::npos) {
65
+ StringRef Line = Str.take_front (Eol + 1 );
66
+ if (!Line.empty ())
67
+ writeWithPrefix (Line);
68
+ HasPendingNewline = true ;
69
+ Str = Str.drop_front (Eol + 1 );
70
+ Eol = Str.find (' \n ' );
71
+ }
72
+ if (!Str.empty ())
73
+ writeWithPrefix (Str);
53
74
}
54
- ~LogWithNewline () { os << ' \n ' ; }
55
- template <typename T> raw_ostream &operator <<(const T &t) && {
56
- return os << t;
75
+ void emitPrefix () { Os.write (Prefix.c_str (), Prefix.size ()); }
76
+ void writeWithPrefix (StringRef Str) {
77
+ if (HasPendingNewline) {
78
+ emitPrefix ();
79
+ HasPendingNewline = false ;
80
+ }
81
+ Os.write (Str.data (), Str.size ());
57
82
}
58
83
59
- // Prevent copying, as this class manages newline responsibility and is
60
- // intended for use as a temporary.
61
- LogWithNewline (const LogWithNewline &) = delete ;
62
- LogWithNewline &operator =(const LogWithNewline &) = delete ;
63
- LogWithNewline &operator =(LogWithNewline &&) = delete ;
64
- static constexpr const char *getShortFileName (const char *path) {
65
- // Remove the path prefix from the file name.
66
- const char *filename = path;
67
- for (const char *p = path; *p != ' \0 ' ; ++p) {
68
- if (*p == ' /' || *p == ' \\ ' ) {
69
- filename = p + 1 ;
70
- }
84
+ public:
85
+ explicit raw_ldbg_ostream (std::string Prefix, raw_ostream &Os)
86
+ : Prefix(std::move(Prefix)), Os(Os) {
87
+ SetUnbuffered ();
88
+ }
89
+ ~raw_ldbg_ostream () final {
90
+ flushEol ();
91
+ Os << ' \n ' ;
92
+ }
93
+ void flushEol () {
94
+ if (HasPendingNewline) {
95
+ emitPrefix ();
96
+ HasPendingNewline = false ;
71
97
}
72
- return filename;
73
98
}
74
99
75
- private:
76
- raw_ostream &os;
100
+ // / Forward the current_pos method to the underlying stream.
101
+ uint64_t current_pos () const final { return Os.tell (); }
102
+
103
+ // / Some of the `<<` operators expect an lvalue, so we trick the type system.
104
+ raw_ldbg_ostream &asLvalue () { return *this ; }
77
105
};
106
+
107
+ // / Remove the path prefix from the file name.
108
+ static LLVM_ATTRIBUTE_UNUSED constexpr const char *
109
+ getShortFileName (const char *path) {
110
+ const char *filename = path;
111
+ for (const char *p = path; *p != ' \0 ' ; ++p) {
112
+ if (*p == ' /' || *p == ' \\ ' )
113
+ filename = p + 1 ;
114
+ }
115
+ return filename;
116
+ }
117
+
118
+ // / Compute the prefix for the debug log in the form of:
119
+ // / "[DebugType] File:Line "
120
+ // / Where the File is the file name without the path prefix.
121
+ static LLVM_ATTRIBUTE_UNUSED std::string
122
+ computePrefix (const char *DebugType, const char *File, int Line) {
123
+ std::string Prefix;
124
+ raw_string_ostream OsPrefix (Prefix);
125
+ if (DebugType)
126
+ OsPrefix << " [" << DebugType << " ] " ;
127
+ OsPrefix << File << " :" << Line << " " ;
128
+ return OsPrefix.str ();
129
+ }
78
130
} // end namespace impl
79
131
#else
80
132
// As others in Debug, When compiling without assertions, the -debug-* options
0 commit comments