Skip to content

Commit d368d11

Browse files
jpienaarjoker-eph
andauthored
[llvm][support] Add LDBG macro. (llvm#143704)
Add macro that mirror a common usage of logging to output .This makes it easy to have streaming log like behavior while still using the base debug logging. I also wanted to avoid inventing a full logging library here while enabling others to change the sink without too much pain, so put it in its own header (this also avoids making Debug depend on raw_ostream beyond forward reference). The should allow a consistent dev experience without fixing the sink too much. --------- Co-authored-by: Mehdi Amini <[email protected]>
1 parent bd91e8a commit d368d11

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

llvm/include/llvm/Support/DebugLog.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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"
17+
#include "llvm/Support/raw_ostream.h"
18+
19+
namespace llvm {
20+
#ifndef NDEBUG
21+
22+
// Output with given inputs and trailing newline. E.g.,
23+
// LDBG() << "Bitset contains: " << Bitset;
24+
// is equivalent to
25+
// LLVM_DEBUG(dbgs() << DEBUG_TYPE << " [" << __FILE__ << ":" << __LINE__
26+
// << "] " << "Bitset contains: " << Bitset << "\n");
27+
#define LDBG() DEBUGLOG_WITH_STREAM_AND_TYPE(llvm::dbgs(), DEBUG_TYPE)
28+
29+
#define DEBUGLOG_WITH_STREAM_AND_TYPE(STREAM, TYPE) \
30+
for (bool _c = (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)); _c; \
31+
_c = false) \
32+
::llvm::impl::LogWithNewline(TYPE, __FILE__, __LINE__, (STREAM))
33+
34+
namespace impl {
35+
class LogWithNewline {
36+
public:
37+
LogWithNewline(const char *debug_type, const char *file, int line,
38+
raw_ostream &os)
39+
: os(os) {
40+
if (debug_type)
41+
os << debug_type << " ";
42+
os << "[" << file << ":" << line << "] ";
43+
}
44+
~LogWithNewline() { os << '\n'; }
45+
template <typename T> raw_ostream &operator<<(const T &t) && {
46+
return os << t;
47+
}
48+
49+
// Prevent copying, as this class manages newline responsibility and is
50+
// intended for use as a temporary.
51+
LogWithNewline(const LogWithNewline &) = delete;
52+
LogWithNewline &operator=(const LogWithNewline &) = delete;
53+
LogWithNewline &operator=(LogWithNewline &&) = delete;
54+
55+
private:
56+
raw_ostream &os;
57+
};
58+
} // end namespace impl
59+
#else
60+
// As others in Debug, When compiling without assertions, the -debug-* options
61+
// and all inputs too LDBG() are ignored.
62+
#define LDBG() \
63+
for (bool _c = false; _c; _c = false) \
64+
::llvm::nulls()
65+
#endif
66+
} // end namespace llvm
67+
68+
#endif // LLVM_SUPPORT_DEBUGLOG_H

llvm/unittests/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ add_llvm_unittest(SupportTests
3131
DataExtractorTest.cpp
3232
DebugCounterTest.cpp
3333
DebugTest.cpp
34+
DebugLogTest.cpp
3435
DivisionByConstantTest.cpp
3536
DJBTest.cpp
3637
EndianStreamTest.cpp
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===- llvm/unittest/Support/DebugLogTest.cpp -----------------------------===//
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+
9+
#include "llvm/Support/DebugLog.h"
10+
#include "llvm/Support/raw_ostream.h"
11+
#include "gmock/gmock.h"
12+
#include "gtest/gtest.h"
13+
14+
#include <string>
15+
using namespace llvm;
16+
using testing::Eq;
17+
using testing::HasSubstr;
18+
19+
#ifndef NDEBUG
20+
TEST(DebugLogTest, Basic) {
21+
llvm::DebugFlag = true;
22+
static const char *DT[] = {"A", "B"};
23+
24+
// Clear debug types.
25+
setCurrentDebugTypes(DT, 0);
26+
{
27+
std::string str;
28+
raw_string_ostream os(str);
29+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, nullptr) << "NoType";
30+
EXPECT_TRUE(StringRef(os.str()).starts_with('['));
31+
EXPECT_TRUE(StringRef(os.str()).ends_with("NoType\n"));
32+
}
33+
34+
setCurrentDebugTypes(DT, 2);
35+
{
36+
std::string str;
37+
raw_string_ostream os(str);
38+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "A";
39+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << "B";
40+
EXPECT_THAT(os.str(), AllOf(HasSubstr("A\n"), HasSubstr("B\n")));
41+
}
42+
43+
setCurrentDebugType("A");
44+
{
45+
std::string str;
46+
raw_string_ostream os(str);
47+
// Just check that the macro doesn't result in dangling else.
48+
if (true)
49+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "A";
50+
else
51+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "B";
52+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << "B";
53+
EXPECT_THAT(os.str(), AllOf(HasSubstr("A\n"), Not(HasSubstr("B\n"))));
54+
55+
int count = 0;
56+
auto inc = [&]() { return ++count; };
57+
EXPECT_THAT(count, Eq(0));
58+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << inc();
59+
EXPECT_THAT(count, Eq(1));
60+
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << inc();
61+
EXPECT_THAT(count, Eq(1));
62+
}
63+
}
64+
#else
65+
TEST(DebugLogTest, Basic) {
66+
// LDBG should be compiled out in NDEBUG, so just check it compiles and has
67+
// no effect.
68+
llvm::DebugFlag = true;
69+
static const char *DT[] = {};
70+
setCurrentDebugTypes(DT, 0);
71+
int count = 0;
72+
auto inc = [&]() { return ++count; };
73+
EXPECT_THAT(count, Eq(0));
74+
LDBG() << inc();
75+
EXPECT_THAT(count, Eq(0));
76+
}
77+
#endif

0 commit comments

Comments
 (0)