-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Default DEBUG_TYPE to the current filename for logging #158494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-llvm-support Author: Mehdi Amini (joker-eph) ChangesThis makes it optional to define a debug type and uses the current FileName instead. This both reduced the size of the prefix printed by LDBG() and makes it possible to pass a filename to Full diff: https://github.com/llvm/llvm-project/pull/158494.diff 3 Files Affected:
diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst
index 0fa91bcfe2d10..0ade433a7f029 100644
--- a/llvm/docs/ProgrammersManual.rst
+++ b/llvm/docs/ProgrammersManual.rst
@@ -1169,7 +1169,8 @@ It also supports a `level` argument to control the verbosity of the output.
LDBG(2) << "I am here!";
-A ``DEBUG_TYPE`` macro should be defined in the file before using ``LDBG()``.
+A ``DEBUG_TYPE`` macro may optionally be defined in the file before using
+``LDBG()``, otherwise the file name is used as the debug type.
The file name and line number are automatically added to the output, as well as
a terminating newline.
@@ -1180,7 +1181,7 @@ The debug output can be enabled by passing the ``-debug`` command line argument.
$ opt < a.bc > /dev/null -mypass
<no output>
$ opt < a.bc > /dev/null -mypass -debug
- [my-pass:2] MyPass.cpp:123 I am here!
+ [2 my-pass MyPass.cpp:123 I am here!
While `LDBG()` is useful to add debug output to your code, there are cases
where you may need to guard a block of code with a debug check. The
@@ -1222,29 +1223,29 @@ Fine grained debug info with ``DEBUG_TYPE`` and the ``-debug-only`` option
Sometimes you may find yourself in a situation where enabling ``-debug`` just
turns on **too much** information (such as when working on the code generator).
If you want to enable debug information with more fine-grained control, you
-should define the ``DEBUG_TYPE`` macro and use the ``-debug-only`` option as
-follows:
+can control the debug type and level with associate with each logging statement
+as follows:
.. code-block:: c++
- #define DEBUG_TYPE "foo"
+ #define DEBUG_TYPE "foo" // Optional: the file name is used insted if not defined
LDBG(2) << "Hello,";
// DEBUG_TYPE can be overridden locally, here with "bar"
LDBG("bar", 3) << "'bar' debug type";
-A more fine-grained control can be achieved by passing the ``-debug-only``
-command line argument:
+A more fine-grained control of the output can be achieved by passing the
+``-debug-only`` command line argument:
.. code-block:: none
$ opt < a.bc > /dev/null -mypass -debug-only=foo
- [foo:2] MyPass.cpp:123 Hello,
+ [2 foo MyPass.cpp:123] Hello,
$ opt < a.bc > /dev/null -mypass -debug-only=foo,bar
- [foo:2] MyPass.cpp:123 Hello,
- [bar:3] MyPass.cpp:124 World!
+ [2 foo MyPass.cpp:123] Hello,
+ [3 bar MyPass.cpp:124] World!
$ opt < a.bc > /dev/null -mypass -debug-only=bar
- [bar:3] MyPass.cpp:124 World!
+ [3 bar MyPass.cpp:124] World!
The debug-only argument is a comma separated list of debug types and levels.
The level is an optional integer setting the maximum debug level to enable:
@@ -1252,9 +1253,9 @@ The level is an optional integer setting the maximum debug level to enable:
.. code-block:: none
$ opt < a.bc > /dev/null -mypass -debug-only=foo:2,bar:2
- [foo:2] MyPass.cpp:123 Hello,
+ [2 foo MyPass.cpp:123] Hello,
$ opt < a.bc > /dev/null -mypass -debug-only=foo:1,bar:3
- [bar:3] MyPass.cpp:124 World!
+ [3 bar MyPass.cpp:124] World!
Instead of opting in specific debug types, the ``-debug-only`` option also
works to filter out debug output for specific debug types, by omitting the
@@ -1263,7 +1264,7 @@ level (or setting it to 0):
.. code-block:: none
$ opt < a.bc > /dev/null -mypass -debug-only=foo:
- [bar:3] MyPass.cpp:124 World!
+ [3 bar MyPass.cpp:124] World!
$ opt < a.bc > /dev/null -mypass -debug-only=bar:0,foo:
diff --git a/llvm/include/llvm/Support/DebugLog.h b/llvm/include/llvm/Support/DebugLog.h
index c1e1648c3b546..41d2fb9ccddb9 100644
--- a/llvm/include/llvm/Support/DebugLog.h
+++ b/llvm/include/llvm/Support/DebugLog.h
@@ -196,22 +196,10 @@ constexpr ::llvm::StringRef strip_quotes(const char *Str) {
return S;
}
-/// Fail compilation if DEBUG_TYPE is not defined.
-/// This is a workaround for GCC <=12 and clang <=16 which do not support
-/// static_assert in templated constexpr functions.
-#if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 12) || \
- (defined(__clang__) && __clang_major__ <= 16)
-#define MISSING_DEBUG_TYPE() \
- extern void missing_DEBUG_TYPE(void); \
- missing_DEBUG_TYPE();
-#else
-#define MISSING_DEBUG_TYPE() static_assert(false, "DEBUG_TYPE is not defined");
-#endif
-
/// Helper to provide the default level (=1) or type (=DEBUG_TYPE). This is used
/// when a single argument is passed to LDBG() (or LDBG_OS()), if it is an
-/// integer we return DEBUG_TYPE and if it is a string we return 1. This fails
-/// with a static_assert if we pass an integer and DEBUG_TYPE is not defined.
+/// integer we return DEBUG_TYPE and if it is a string we return 1.
+/// When DEBUG_TYPE is not defined, we return the current file name instead.
#define LDBG_GET_DEFAULT_TYPE_OR_LEVEL(LEVEL_OR_TYPE) \
[](auto LevelOrType) { \
if constexpr (std::is_integral_v<decltype(LevelOrType)>) { \
@@ -219,7 +207,7 @@ constexpr ::llvm::StringRef strip_quotes(const char *Str) {
if constexpr (DebugType[0] == '"') { \
return ::llvm::impl::strip_quotes(DebugType); \
} else { \
- MISSING_DEBUG_TYPE(); \
+ return __LLVM_FILE_NAME__; \
} \
} else { \
return 1; \
@@ -331,9 +319,10 @@ static LLVM_ATTRIBUTE_UNUSED std::string
computePrefix(StringRef DebugType, const char *File, int Line, int Level) {
std::string Prefix;
raw_string_ostream OsPrefix(Prefix);
- if (!DebugType.empty())
- OsPrefix << "[" << DebugType << ":" << Level << "] ";
- OsPrefix << File << ":" << Line << " ";
+ OsPrefix << "[" << Level << " ";
+ if (!DebugType.empty() && DebugType != File)
+ OsPrefix << DebugType << " ";
+ OsPrefix << File << ":" << Line << "] ";
return OsPrefix.str();
}
/// Overload allowing to swap the order of the DebugType and Level arguments.
diff --git a/llvm/unittests/Support/DebugLogTest.cpp b/llvm/unittests/Support/DebugLogTest.cpp
index da3851ed86b35..e6f567409f42c 100644
--- a/llvm/unittests/Support/DebugLogTest.cpp
+++ b/llvm/unittests/Support/DebugLogTest.cpp
@@ -28,7 +28,7 @@ TEST(DebugLogTest, Basic) {
std::string str;
raw_string_ostream os(str);
LDGB_STREAM_LEVEL_AND_TYPE(os, "", 0) << "NoType";
- EXPECT_FALSE(StringRef(os.str()).starts_with('['));
+ EXPECT_TRUE(StringRef(os.str()).starts_with('['));
EXPECT_TRUE(StringRef(os.str()).ends_with("NoType\n"));
}
@@ -77,8 +77,8 @@ TEST(DebugLogTest, BasicWithLevel) {
for (int level : llvm::seq<int>(0, 4))
LDBG_STREAM_LEVEL_TYPE_FILE_AND_LINE(os, level, type, type, level)
<< level;
- EXPECT_EQ(os.str(), "[A:0] A:0 0\n[A:1] A:1 1\n[A:2] A:2 2\n[A:3] A:3 "
- "3\n[B:0] B:0 0\n[B:1] B:1 1\n[C:0] C:0 0\n");
+ EXPECT_EQ(os.str(), "[0 A:0] 0\n[1 A:1] 1\n[2 A:2] 2\n[3 A:3] 3\n[0 B:0] "
+ "0\n[1 B:1] 1\n[0 C:0] 0\n");
}
TEST(DebugLogTest, NegativeLevel) {
@@ -92,9 +92,10 @@ TEST(DebugLogTest, NegativeLevel) {
raw_string_ostream os(str);
for (auto type : {"A", "B"})
for (int level : llvm::seq<int>(0, 2))
- LDBG_STREAM_LEVEL_TYPE_FILE_AND_LINE(os, level, type, type, level)
+ LDBG_STREAM_LEVEL_TYPE_FILE_AND_LINE(
+ os, level, type, (std::string(type) + ".cpp").c_str(), level)
<< level;
- EXPECT_EQ(os.str(), "[A:0] A:0 0\n[B:0] B:0 0\n[B:1] B:1 1\n");
+ EXPECT_EQ(os.str(), "[0 A A.cpp:0] 0\n[0 B B.cpp:0] 0\n[1 B B.cpp:1] 1\n");
}
TEST(DebugLogTest, StreamPrefix) {
@@ -141,35 +142,71 @@ TEST(DebugLogTest, LDBG_MACROS) {
#define LDBG_STREAM DebugOs
#define DEBUG_TYPE "A"
LDBG() << "Hello, world!";
- ExpectedOs << "[A:1] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[1 A " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
// Test with a level, no type.
LDBG(2) << "Hello, world!";
- ExpectedOs << "[A:2] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[2 A " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
-// Now the type will be explicit, check we don't use DEBUG_TYPE.
+// Now check when we don't use DEBUG_TYPE, the file name is implicitly used
+// instead.
#undef DEBUG_TYPE
+ // Repeat the tests above, they won't match since the debug types defined
+ // above don't match the file name.
+ LDBG() << "Hello, world!";
+ EXPECT_EQ(DebugOs.str(), "");
+ Str.clear();
+ StrExpected.clear();
+
+ // Test with a level, no type.
+ LDBG(2) << "Hello, world!";
+ EXPECT_EQ(DebugOs.str(), "");
+ Str.clear();
+ StrExpected.clear();
+
+ // Now enable the debug types that match the file name.
+ auto fileNameAndLevel = std::string(__LLVM_FILE_NAME__) + ":3";
+ static const char *DT2[] = {fileNameAndLevel.c_str(), "B:2"};
+ setCurrentDebugTypes(DT2, sizeof(DT2) / sizeof(DT2[0]));
+
+ // Repeat the tests above, they should match now.
+
+ LDBG() << "Hello, world!";
+ ExpectedOs << "[1 " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
+ EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
+ Str.clear();
+ StrExpected.clear();
+
+ // Test with a level, no type.
+ LDBG(2) << "Hello, world!";
+ ExpectedOs << "[2 " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
+ EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
+ Str.clear();
+ StrExpected.clear();
+
// Test with a type
LDBG("B") << "Hello, world!";
- ExpectedOs << "[B:1] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[1 B " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
// Test with a type and a level
LDBG("B", 2) << "Hello, world!";
- ExpectedOs << "[B:2] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[2 B " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
@@ -181,6 +218,8 @@ TEST(DebugLogTest, LDBG_MACROS) {
// Test with a level not enabled.
LDBG("B", 3) << "Hello, world!";
EXPECT_EQ(DebugOs.str(), "");
+ LDBG(__LLVM_FILE_NAME__, 4) << "Hello, world!";
+ EXPECT_EQ(DebugOs.str(), "");
}
TEST(DebugLogTest, LDBG_OS_MACROS) {
@@ -195,35 +234,70 @@ TEST(DebugLogTest, LDBG_OS_MACROS) {
#define LDBG_STREAM DebugOs
#define DEBUG_TYPE "A"
LDBG_OS([](raw_ostream &Os) { Os << "Hello, world!"; });
- ExpectedOs << "[A:1] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[1 A " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
// Test with a level, no type.
LDBG_OS(2, [](raw_ostream &Os) { Os << "Hello, world!"; });
- ExpectedOs << "[A:2] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[2 A " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
-// Now the type will be explicit, check we don't use DEBUG_TYPE.
+// Now check when we don't use DEBUG_TYPE, the file name is implicitly used
+// instead.
#undef DEBUG_TYPE
+ // Repeat the tests above, they won't match since the debug types defined
+ // above don't match the file name.
+ LDBG_OS([](raw_ostream &Os) { Os << "Hello, world!"; });
+ EXPECT_EQ(DebugOs.str(), "");
+ Str.clear();
+ StrExpected.clear();
+
+ // Test with a level, no type.
+ LDBG_OS(2, [](raw_ostream &Os) { Os << "Hello, world!"; });
+ EXPECT_EQ(DebugOs.str(), "");
+ Str.clear();
+ StrExpected.clear();
+
+ // Now enable the debug types that match the file name.
+ auto fileNameAndLevel = std::string(__LLVM_FILE_NAME__) + ":3";
+ static const char *DT2[] = {fileNameAndLevel.c_str(), "B:2"};
+ setCurrentDebugTypes(DT2, sizeof(DT2) / sizeof(DT2[0]));
+
+ // Repeat the tests above, they should match now.
+ LDBG_OS([](raw_ostream &Os) { Os << "Hello, world!"; });
+ ExpectedOs << "[1 " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
+ EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
+ Str.clear();
+ StrExpected.clear();
+
+ // Test with a level, no type.
+ LDBG_OS(2, [](raw_ostream &Os) { Os << "Hello, world!"; });
+ ExpectedOs << "[2 " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
+ EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
+ Str.clear();
+ StrExpected.clear();
+
// Test with a type.
LDBG_OS("B", [](raw_ostream &Os) { Os << "Hello, world!"; });
- ExpectedOs << "[B:1] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[1 B " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
// Test with a type and a level
LDBG_OS("B", 2, [](raw_ostream &Os) { Os << "Hello, world!"; });
- ExpectedOs << "[B:2] " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
- << " Hello, world!\n";
+ ExpectedOs << "[2 B " << __LLVM_FILE_NAME__ << ":" << (__LINE__ - 1)
+ << "] Hello, world!\n";
EXPECT_EQ(DebugOs.str(), ExpectedOs.str());
Str.clear();
StrExpected.clear();
|
a9c1afc
to
0c21308
Compare
joker-eph
commented
Sep 14, 2025
4ef5077
to
1f9fe88
Compare
jpienaar
reviewed
Sep 15, 2025
1f9fe88
to
79a18f4
Compare
jpienaar
approved these changes
Sep 15, 2025
This makes it optional to define a debug type and uses the current FileName instead. This both reduced the size of the prefix printed by LDBG() and makes it possible to pass a filename to `--debug-only` to filter on.
79a18f4
to
c94f7bb
Compare
SeongjaeP
pushed a commit
to SeongjaeP/llvm-project
that referenced
this pull request
Sep 23, 2025
This makes it optional to define a debug type and uses the current FileName instead. This both reduced the size of the prefix printed by LDBG() and makes it possible to pass a filename to `--debug-only` to filter on.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This makes it optional to define a debug type and uses the current FileName instead. This both reduced the size of the prefix printed by LDBG() and makes it possible to pass a filename to
--debug-only
to filter on.