@@ -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
+ }
35
+ // When __SHORT_FILE__ is not define, 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 {
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
+ if (!Str.empty ()) {
60
+ if (HasPendingNewline) {
61
+ emitPrefix ();
62
+ HasPendingNewline = false ;
63
+ }
64
+ }
65
+ auto Eol = Str.find (' \n ' );
66
+ while (Eol != StringRef::npos) {
67
+ StringRef Line = Str.take_front (Eol + 1 );
68
+ if (!Line.empty ()) {
69
+ if (HasPendingNewline) {
70
+ emitPrefix ();
71
+ HasPendingNewline = false ;
72
+ }
73
+ Os.write (Line.data (), Line.size ());
74
+ }
75
+ HasPendingNewline = true ;
76
+ Str = Str.drop_front (Eol + 1 );
77
+ Eol = Str.find (' \n ' );
78
+ }
79
+ if (!Str.empty ()) {
80
+ if (HasPendingNewline) {
81
+ emitPrefix ();
82
+ HasPendingNewline = false ;
83
+ }
84
+ Os.write (Str.data (), Str.size ());
85
+ }
86
+ }
87
+ void emitPrefix () { Os.write (Prefix.c_str (), Prefix.size ()); }
88
+
43
89
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 << " " ;
90
+ explicit raw_ldbg_ostream (std::string Prefix, raw_ostream &Os)
91
+ : Prefix(std::move(Prefix)), Os(Os) {
92
+ SetUnbuffered ();
53
93
}
54
- ~LogWithNewline () { os << ' \n ' ; }
55
- template < typename T> raw_ostream & operator <<( const T &t) && {
56
- return os << t ;
94
+ ~raw_ldbg_ostream () final {
95
+ flushEol ();
96
+ Os << ' \n ' ;
57
97
}
58
-
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
- }
98
+ void flushEol () {
99
+ if (HasPendingNewline) {
100
+ emitPrefix ();
101
+ HasPendingNewline = false ;
71
102
}
72
- return filename;
73
103
}
74
104
75
- private:
76
- raw_ostream &os;
105
+ // / Forward the current_pos method to the underlying stream.
106
+ uint64_t current_pos () const final { return Os. tell (); }
77
107
};
108
+
109
+ // / Remove the path prefix from the file name.
110
+ static constexpr const char *getShortFileName (const char *path) {
111
+ for (const char *p = path; *p != ' \0 ' ; ++p) {
112
+ if (*p == ' /' || *p == ' \\ ' )
113
+ path = p + 1 ;
114
+ }
115
+ return path;
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 std::string computePrefix (const char *DebugType, const char *File,
122
+ 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