Skip to content

Conversation

joker-eph
Copy link
Collaborator

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.

@llvmbot
Copy link
Member

llvmbot commented Sep 14, 2025

@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-llvm-support

Author: Mehdi Amini (joker-eph)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/158494.diff

3 Files Affected:

  • (modified) llvm/docs/ProgrammersManual.rst (+15-14)
  • (modified) llvm/include/llvm/Support/DebugLog.h (+7-18)
  • (modified) llvm/unittests/Support/DebugLogTest.cpp (+97-23)
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();

@joker-eph joker-eph force-pushed the ldbg_filename branch 4 times, most recently from a9c1afc to 0c21308 Compare September 14, 2025 16:26
@llvmbot llvmbot added the mlir label Sep 14, 2025
@joker-eph joker-eph force-pushed the ldbg_filename branch 3 times, most recently from 4ef5077 to 1f9fe88 Compare September 14, 2025 20:04
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.
@joker-eph joker-eph enabled auto-merge (squash) September 15, 2025 15:58
@joker-eph joker-eph merged commit 53cda13 into llvm:main Sep 15, 2025
10 checks passed
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants