LLVM: include/llvm/Support/DebugLog.h Source File (original) (raw)

84

85

86

87#define LDBG_STREAM ::llvm::dbgs()

88

89

90

91

92

93

94

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

105

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); \

110 _c; _c = false) \

111 ::llvm::impl::raw_ldbg_ostream{ \

112 ::llvm::impl::computePrefix(TYPE_OR_LEVEL, FILE, LINE, LEVEL_OR_TYPE), \

113 (STREAM), true, \

114 true} \

115 .asLvalue()

116

117

118

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

127

128

129

130

131#define LDBG_TYPE_AND_LEVEL(TYPE, LEVEL) \

132 LDGB_STREAM_LEVEL_AND_TYPE(LDBG_STREAM, static_cast<const char *>(TYPE), \

133 (LEVEL))

134

135

136

137

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

145

146

147

148

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

161

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), true, \

169 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

184

185

186

187

188

189

190

191

192constexpr ::llvm::StringRef strip_quotes(const char *Str) {

194 if (Str[0] == '"' && Str[S.size() - 1] == '"')

196 return S;

197}

198

199

200

201

202

203#define LDBG_GET_DEFAULT_TYPE_OR_LEVEL(LEVEL_OR_TYPE) \

204 [](auto LevelOrType) { \

205 if constexpr (std::is_integral_v<decltype(LevelOrType)>) { \

206 constexpr const char *DebugType = LDBG_GET_DEBUG_TYPE_STR(); \

207 if constexpr (DebugType[0] == '"') { \

208 return ::llvm::impl::strip_quotes(DebugType); \

209 } else { \

210 return __LLVM_FILE_NAME__; \

211 } \

212 } else { \

213 return 1; \

214 } \

215 }(LEVEL_OR_TYPE)

216

217

218

219#define LDBG_GET_DEBUG_TYPE_STR__(X) #X

220#define LDBG_GET_DEBUG_TYPE_STR_(X) LDBG_GET_DEBUG_TYPE_STR__(X)

221#define LDBG_GET_DEBUG_TYPE_STR() LDBG_GET_DEBUG_TYPE_STR_(DEBUG_TYPE)

222

223

224[[maybe_unused]] static bool ldbgIsCurrentDebugType(StringRef Type, int Level) {

225 return ::llvm::isCurrentDebugType(Type.str().c_str(), Level);

226}

227[[maybe_unused]] static bool ldbgIsCurrentDebugType(int Level, StringRef Type) {

228 return ::llvm::isCurrentDebugType(Type.str().c_str(), Level);

229}

230

231

232

233class LLVM_ABI raw_ldbg_ostream final : public raw_ostream {

234 std::string Prefix;

235 raw_ostream &Os;

236 bool ShouldPrefixNextString;

237 bool ShouldEmitNewLineOnDestruction;

238

239

240

241 void write_impl(const char *Ptr, size_t Size) final {

242 auto Str = StringRef(Ptr, Size);

243 auto Eol = Str.find('\n');

244 // Handle `\n` occurring in the string, ensure to print the prefix at the

245 // beginning of each line.

246 while (Eol != StringRef::npos) {

247 // Take the line up to the newline (including the newline).

248 StringRef Line = Str.take_front(Eol + 1);

249 if (!Line.empty())

250 writeWithPrefix(Line);

251 // We printed a newline, record here to print a prefix.

252 ShouldPrefixNextString = true;

253 Str = Str.drop_front(Eol + 1);

254 Eol = Str.find('\n');

255 }

256 if (!Str.empty())

257 writeWithPrefix(Str);

258 }

259 void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); }

260 void writeWithPrefix(StringRef Str) {

261 if (ShouldPrefixNextString) {

262 emitPrefix();

263 ShouldPrefixNextString = false;

264 }

265 Os.write(Str.data(), Str.size());

266 }

267

268public:

269 explicit raw_ldbg_ostream(std::string Prefix, raw_ostream &Os,

270 bool ShouldPrefixNextString = true,

271 bool ShouldEmitNewLineOnDestruction = false)

272 : Prefix(std::move(Prefix)), Os(Os),

273 ShouldPrefixNextString(ShouldPrefixNextString),

274 ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) {

275 SetUnbuffered();

276 }

277 ~raw_ldbg_ostream() final {

278 if (ShouldEmitNewLineOnDestruction)

279 Os << '\n';

280 }

281

282

283 uint64_t current_pos() const final { return Os.tell(); }

284

285

286

287 raw_ldbg_ostream &asLvalue() { return *this; }

288};

289

290

291class RAIINewLineStream final : public raw_ostream {

292 raw_ostream &Os;

293

294public:

295 RAIINewLineStream(raw_ostream &Os) : Os(Os) { SetUnbuffered(); }

296 ~RAIINewLineStream() override { Os << '\n'; }

297 void write_impl(const char *Ptr, size_t Size) final { Os.write(Ptr, Size); }

298 uint64_t current_pos() const final { return Os.tell(); }

299 RAIINewLineStream &asLvalue() { return *this; }

300};

301

302

303[[maybe_unused]] static constexpr const char *

304getShortFileName(const char *path) {

305 const char *filename = path;

306 for (const char *p = path; *p != '\0'; ++p) {

307 if (*p == '/' || *p == '\\')

308 filename = p + 1;

309 }

310 return filename;

311}

312

313

314

315

316[[maybe_unused]] static std::string

317computePrefix(StringRef DebugType, const char *File, int Line, int Level) {

318 std::string Prefix;

319 raw_string_ostream OsPrefix(Prefix);

320 OsPrefix << "[";

321 if (!DebugType.empty() && DebugType != File)

322 OsPrefix << DebugType << " ";

323 OsPrefix << File << ":" << Line << " " << Level << "] ";

324 return OsPrefix.str();

325}

326

327[[maybe_unused]] static std::string

328computePrefix(int Level, const char *File, int Line, StringRef DebugType) {

329 return computePrefix(DebugType, File, Line, Level);

330}

331

332} // end namespace impl

334// As others in Debug, When compiling without assertions, the -debug-* options

335// and all inputs too LDBG() are ignored.