Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions llvm/include/llvm/Support/DebugLog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===- llvm/Support/DebugLog.h - Logging like debug output ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This file contains macros for logging like debug output. It builds upon the
// support in Debug.h but provides a utility function for common debug output
// style.
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_DEBUGLOG_H
#define LLVM_SUPPORT_DEBUGLOG_H

#include "llvm/Support/Debug.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered making this part of the Debug.h header directly?

#include "llvm/Support/raw_ostream.h"

namespace llvm {
#ifndef NDEBUG

// Output with given inputs and trailing newline. E.g.,
// LDBG() << "Bitset contains: " << Bitset;
// is equivalent to
// LLVM_DEBUG(dbgs() << DEBUG_TYPE << " [" << __FILE__ << ":" << __LINE__
// << "] " << "Bitset contains: " << Bitset << "\n");
#define LDBG() DEBUGLOG_WITH_STREAM_AND_TYPE(llvm::dbgs(), DEBUG_TYPE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we prefix this with LLVM_? In the past, we used DEBUG instead of LLVM_DEBUG which caused naming collisions downstream: https://discourse.llvm.org/t/rfc-change-debug-macro-to-llvm-debug/48092 . I wonder if LDBG may be terse enough to run into similar issues.


#define DEBUGLOG_WITH_STREAM_AND_TYPE(STREAM, TYPE) \
for (bool _c = (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)); _c; \
_c = false) \
::llvm::impl::LogWithNewline(TYPE, __FILE__, __LINE__, (STREAM))

namespace impl {
class LogWithNewline {
public:
LogWithNewline(const char *debug_type, const char *file, int line,
raw_ostream &os)
: os(os) {
if (debug_type)
os << debug_type << " ";
os << "[" << file << ":" << line << "] ";
}
~LogWithNewline() { os << '\n'; }
template <typename T> raw_ostream &operator<<(const T &t) && {
return os << t;
}

// Prevent copying, as this class manages newline responsibility and is
// intended for use as a temporary.
LogWithNewline(const LogWithNewline &) = delete;
LogWithNewline &operator=(const LogWithNewline &) = delete;
LogWithNewline &operator=(LogWithNewline &&) = delete;

private:
raw_ostream &os;
};
} // end namespace impl
#else
// As others in Debug, When compiling without assertions, the -debug-* options
// and all inputs too LDBG() are ignored.
#define LDBG() \
for (bool _c = false; _c; _c = false) \
::llvm::nulls()
#endif
} // end namespace llvm

#endif // LLVM_SUPPORT_DEBUGLOG_H
1 change: 1 addition & 0 deletions llvm/unittests/Support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_llvm_unittest(SupportTests
DataExtractorTest.cpp
DebugCounterTest.cpp
DebugTest.cpp
DebugLogTest.cpp
DivisionByConstantTest.cpp
DJBTest.cpp
EndianStreamTest.cpp
Expand Down
77 changes: 77 additions & 0 deletions llvm/unittests/Support/DebugLogTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//===- llvm/unittest/Support/DebugLogTest.cpp -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/DebugLog.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include <string>
using namespace llvm;
using testing::Eq;
using testing::HasSubstr;

#ifndef NDEBUG
TEST(DebugLogTest, Basic) {
llvm::DebugFlag = true;
static const char *DT[] = {"A", "B"};

// Clear debug types.
setCurrentDebugTypes(DT, 0);
{
std::string str;
raw_string_ostream os(str);
DEBUGLOG_WITH_STREAM_AND_TYPE(os, nullptr) << "NoType";
EXPECT_TRUE(StringRef(os.str()).starts_with('['));
EXPECT_TRUE(StringRef(os.str()).ends_with("NoType\n"));
}

setCurrentDebugTypes(DT, 2);
{
std::string str;
raw_string_ostream os(str);
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "A";
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << "B";
EXPECT_THAT(os.str(), AllOf(HasSubstr("A\n"), HasSubstr("B\n")));
}

setCurrentDebugType("A");
{
std::string str;
raw_string_ostream os(str);
// Just check that the macro doesn't result in dangling else.
if (true)
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "A";
else
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << "B";
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << "B";
EXPECT_THAT(os.str(), AllOf(HasSubstr("A\n"), Not(HasSubstr("B\n"))));

int count = 0;
auto inc = [&]() { return ++count; };
EXPECT_THAT(count, Eq(0));
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "A") << inc();
EXPECT_THAT(count, Eq(1));
DEBUGLOG_WITH_STREAM_AND_TYPE(os, "B") << inc();
EXPECT_THAT(count, Eq(1));
}
}
#else
TEST(DebugLogTest, Basic) {
// LDBG should be compiled out in NDEBUG, so just check it compiles and has
// no effect.
llvm::DebugFlag = true;
static const char *DT[] = {};
setCurrentDebugTypes(DT, 0);
int count = 0;
auto inc = [&]() { return ++count; };
EXPECT_THAT(count, Eq(0));
LDBG() << inc();
EXPECT_THAT(count, Eq(0));
}
#endif