From 3fcd3669e3dc7c5ba72d3bfceef42b2f833254ec Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Wed, 8 Jun 2022 16:48:15 -0700 Subject: [PATCH] [ORC] Add an output stream operator for SymbolStringPool. Handy for checking string pool state, e.g. when debugging dangling-pool-entry errors. --- llvm/include/llvm/ExecutionEngine/Orc/DebugUtils.h | 3 +++ .../llvm/ExecutionEngine/Orc/SymbolStringPool.h | 7 +++++++ llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp | 7 +++++++ .../ExecutionEngine/Orc/SymbolStringPoolTest.cpp | 12 ++++++++++++ 4 files changed, 29 insertions(+) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/DebugUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/DebugUtils.h index 7eb98dfc741e..c4ef06f1fbc6 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/DebugUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/DebugUtils.h @@ -92,6 +92,9 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S); /// Render a LookupKind. raw_ostream &operator<<(raw_ostream &OS, const LookupKind &K); +/// Dump a SymbolStringPool. Useful for debugging dangling-pointer crashes. +raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP); + /// A function object that can be used as an ObjectTransformLayer transform /// to dump object files to disk at a specified path. class DumpObjects { diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h index 63abb196ba49..7e433965c922 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h @@ -19,6 +19,9 @@ #include namespace llvm { + +class raw_ostream; + namespace orc { class SymbolStringPtr; @@ -26,6 +29,10 @@ class SymbolStringPtr; /// String pool for symbol names used by the JIT. class SymbolStringPool { friend class SymbolStringPtr; + + // Implemented in DebugUtils.h. + friend raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP); + public: /// Destroy a SymbolStringPool. ~SymbolStringPool(); diff --git a/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp b/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp index 5b386a458f1f..028bd245fb55 100644 --- a/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/DebugUtils.cpp @@ -297,6 +297,13 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) { llvm_unreachable("Invalid state"); } +raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP) { + std::lock_guard Lock(SSP.PoolMutex); + for (auto &KV : SSP.Pool) + OS << KV.first() << ": " << KV.second << "\n"; + return OS; +} + DumpObjects::DumpObjects(std::string DumpDir, std::string IdentifierOverride) : DumpDir(std::move(DumpDir)), IdentifierOverride(std::move(IdentifierOverride)) { diff --git a/llvm/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp index a68da0be9606..aab465a31257 100644 --- a/llvm/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" +#include "llvm/ExecutionEngine/Orc/DebugUtils.h" #include "gtest/gtest.h" using namespace llvm; @@ -50,4 +51,15 @@ TEST(SymbolStringPool, ClearDeadEntries) { EXPECT_TRUE(SP.empty()) << "pool should be empty"; } +TEST(SymbolStringPool, DebugDump) { + SymbolStringPool SP; + auto A1 = SP.intern("a"); + auto A2 = A1; + auto B = SP.intern("b"); + + std::string DumpString; + raw_string_ostream(DumpString) << SP; + + EXPECT_EQ(DumpString, "a: 2\nb: 1\n"); +} }