[Remarks] Add support for internalizing a remark in a string table
authorFrancis Visoiu Mistrih <francisvm@yahoo.com>
Fri, 6 Sep 2019 17:22:51 +0000 (17:22 +0000)
committerFrancis Visoiu Mistrih <francisvm@yahoo.com>
Fri, 6 Sep 2019 17:22:51 +0000 (17:22 +0000)
In order to keep remarks around, we need to make them tied to a string
table.

Users then can delete the parser and rely on the string table to keep
the memory of the strings alive and deduplicated.

llvm-svn: 371233

llvm/include/llvm/Remarks/RemarkStringTable.h
llvm/lib/Remarks/RemarkStringTable.cpp
llvm/unittests/Remarks/RemarksAPITest.cpp

index be2596d..80d8276 100644 (file)
@@ -51,6 +51,9 @@ struct StringTable {
 
   /// Add a string to the table. It returns an unique ID of the string.
   std::pair<unsigned, StringRef> add(StringRef Str);
+  /// Modify \p R to use strings from this string table. If the string table
+  /// does not contain the strings, it adds them.
+  void internalize(Remark &R);
   /// Serialize the string table to a stream. It is serialized as a little
   /// endian uint64 (the size of the table in bytes) followed by a sequence of
   /// NULL-terminated strings, where the N-th string is the string with the ID N
index 17aa394..0f8a95a 100644 (file)
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Remarks/RemarkStringTable.h"
+#include "llvm/Remarks/Remark.h"
 #include "llvm/Remarks/RemarkParser.h"
 #include "llvm/Support/EndianStream.h"
 #include "llvm/Support/Error.h"
@@ -37,6 +38,22 @@ std::pair<unsigned, StringRef> StringTable::add(StringRef Str) {
   return {KV.first->second, KV.first->first()};
 }
 
+void StringTable::internalize(Remark &R) {
+  auto Impl = [&](StringRef &S) { S = add(S).second; };
+  Impl(R.PassName);
+  Impl(R.RemarkName);
+  Impl(R.FunctionName);
+  if (R.Loc)
+    Impl(R.Loc->SourceFilePath);
+  for (Argument &Arg : R.Args) {
+    // We need to mutate elements from an ArrayRef here.
+    Impl(Arg.Key);
+    Impl(Arg.Val);
+    if (Arg.Loc)
+      Impl(Arg.Loc->SourceFilePath);
+  }
+}
+
 void StringTable::serialize(raw_ostream &OS) const {
   // Emit the sequence of strings.
   for (StringRef Str : serialize()) {
index 23a45e9..19fa90f 100644 (file)
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkStringTable.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -75,3 +76,48 @@ TEST(RemarksAPI, ArgsAsMsg) {
 
   EXPECT_EQ(R.getArgsAsMsg(), "can not do this because of that.");
 }
+
+TEST(RemarksAPI, StringTableInternalize) {
+  remarks::StringTable StrTab;
+
+  // Empty table.
+  EXPECT_EQ(StrTab.SerializedSize, 0UL);
+
+  remarks::Remark R;
+  R.RemarkType = remarks::Type::Missed;
+  R.PassName = "pass";
+  R.RemarkName = "name";
+  R.FunctionName = "func";
+  R.Loc = remarks::RemarkLocation{"path", 3, 4};
+  R.Args.emplace_back();
+  R.Args.back().Key = "keydebug";
+  R.Args.back().Val = "valuedebug";
+  R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
+
+  // Check that internalize starts using the strings from the string table.
+  remarks::Remark R2 = R.clone();
+  StrTab.internalize(R2);
+
+  // Check that the pointers in the remarks are different.
+  EXPECT_NE(R.PassName.data(), R2.PassName.data());
+  EXPECT_NE(R.RemarkName.data(), R2.RemarkName.data());
+  EXPECT_NE(R.FunctionName.data(), R2.FunctionName.data());
+  EXPECT_NE(R.Loc->SourceFilePath.data(), R2.Loc->SourceFilePath.data());
+  EXPECT_NE(R.Args.back().Key.data(), R2.Args.back().Key.data());
+  EXPECT_NE(R.Args.back().Val.data(), R2.Args.back().Val.data());
+  EXPECT_NE(R.Args.back().Loc->SourceFilePath.data(),
+            R2.Args.back().Loc->SourceFilePath.data());
+
+  // Check that the internalized remark is using the pointers from the string table.
+  EXPECT_EQ(StrTab.add(R.PassName).second.data(), R2.PassName.data());
+  EXPECT_EQ(StrTab.add(R.RemarkName).second.data(), R2.RemarkName.data());
+  EXPECT_EQ(StrTab.add(R.FunctionName).second.data(), R2.FunctionName.data());
+  EXPECT_EQ(StrTab.add(R.Loc->SourceFilePath).second.data(),
+            R2.Loc->SourceFilePath.data());
+  EXPECT_EQ(StrTab.add(R.Args.back().Key).second.data(),
+            R2.Args.back().Key.data());
+  EXPECT_EQ(StrTab.add(R.Args.back().Val).second.data(),
+            R2.Args.back().Val.data());
+  EXPECT_EQ(StrTab.add(R.Args.back().Loc->SourceFilePath).second.data(),
+            R2.Args.back().Loc->SourceFilePath.data());
+}