[llvm] 628f11f - [DWARFLinkerParallel] Add StringTable class.

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 5 02:49:32 PDT 2023


Author: Alexey Lapshin
Date: 2023-04-05T11:42:24+02:00
New Revision: 628f11f78d33a182dbd9d8746a6e93dce08a8c44

URL: https://github.com/llvm/llvm-project/commit/628f11f78d33a182dbd9d8746a6e93dce08a8c44
DIFF: https://github.com/llvm/llvm-project/commit/628f11f78d33a182dbd9d8746a6e93dce08a8c44.diff

LOG: [DWARFLinkerParallel] Add StringTable class.

This patch adds StringTable class which is used to prepare
strings for emission into the .debug_str table. Specifically,
this class translates strings if necessary, keeps them in order,
assigns index and offset.

Differential Revision: https://reviews.llvm.org/D147529

Added: 
    llvm/include/llvm/DWARFLinkerParallel/StringTable.h
    llvm/unittests/DWARFLinkerParallel/StringTableTest.cpp

Modified: 
    llvm/include/llvm/DWARFLinkerParallel/StringPool.h
    llvm/unittests/DWARFLinkerParallel/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DWARFLinkerParallel/StringPool.h b/llvm/include/llvm/DWARFLinkerParallel/StringPool.h
index 52fb64cea1d1d..9eb0d759f6a9c 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/StringPool.h
+++ b/llvm/include/llvm/DWARFLinkerParallel/StringPool.h
@@ -75,6 +75,8 @@ class StringPool : public ConcurrentHashTableByPtr<StringRef, StringEntry,
                                  PerThreadStringAllocator, StringPoolEntryInfo>(
             Allocator, InitialSize) {}
 
+  PerThreadStringAllocator &getAllocatorRef() { return Allocator; }
+
 private:
   PerThreadStringAllocator Allocator;
 };

diff  --git a/llvm/include/llvm/DWARFLinkerParallel/StringTable.h b/llvm/include/llvm/DWARFLinkerParallel/StringTable.h
new file mode 100644
index 0000000000000..ac1c39f3dcc66
--- /dev/null
+++ b/llvm/include/llvm/DWARFLinkerParallel/StringTable.h
@@ -0,0 +1,84 @@
+//===- StringTable.h --------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DWARFLINKERPARALLEL_STRINGTABLE_H
+#define LLVM_DWARFLINKERPARALLEL_STRINGTABLE_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DWARFLinkerParallel/StringPool.h"
+
+namespace llvm {
+namespace dwarflinker_parallel {
+
+using StringsVector = SmallVector<StringEntry *>;
+
+/// This class prepares strings for emission into .debug_str table:
+/// translates string if necessary, assigns index and offset, keeps in order.
+class StringTable {
+public:
+  StringTable(StringPool &Strings,
+              std::function<StringRef(StringRef)> StringsTranslator)
+      : Strings(Strings), StringsTranslator(StringsTranslator) {}
+  ~StringTable() {}
+
+  /// Add string to the vector of strings which should be emitted.
+  /// Translate input string if neccessary, assign index and offset.
+  /// \returns updated string entry.
+  StringEntry *add(StringEntry *String) {
+    // Translate string if necessary.
+    if (StringsTranslator)
+      String = Strings.insert(StringsTranslator(String->first())).first;
+
+    // Store String for emission and assign index and offset.
+    if (String->getValue() == nullptr) {
+      DwarfStringPoolEntry *NewEntry =
+          Strings.getAllocatorRef().Allocate<DwarfStringPoolEntry>();
+
+      NewEntry->Symbol = nullptr;
+      NewEntry->Index = StringEntriesForEmission.size();
+
+      if (StringEntriesForEmission.empty())
+        NewEntry->Offset = 0;
+      else {
+        StringEntry *PrevString = StringEntriesForEmission.back();
+        NewEntry->Offset =
+            PrevString->getValue()->Offset + PrevString->getKeyLength() + 1;
+      }
+
+      String->getValue() = NewEntry;
+      StringEntriesForEmission.push_back(String);
+    }
+
+    return String;
+  }
+
+  /// Erase contents of StringsForEmission.
+  void clear() { StringEntriesForEmission.clear(); }
+
+  /// Enumerate all strings in sequential order and call \p Handler for each
+  /// string.
+  void forEach(function_ref<void(DwarfStringPoolEntryRef)> Handler) const {
+    for (const StringEntry *Entry : StringEntriesForEmission)
+      Handler(*Entry);
+  }
+
+protected:
+  /// List of strings for emission.
+  StringsVector StringEntriesForEmission;
+
+  /// String pool for the translated strings.
+  StringPool &Strings;
+
+  /// Translator for the strings.
+  std::function<StringRef(StringRef)> StringsTranslator;
+};
+
+} // end of namespace dwarflinker_parallel
+} // end namespace llvm
+
+#endif // LLVM_DWARFLINKERPARALLEL_STRINGTABLE_H

diff  --git a/llvm/unittests/DWARFLinkerParallel/CMakeLists.txt b/llvm/unittests/DWARFLinkerParallel/CMakeLists.txt
index ca2cb47283483..9f27c03fe46f7 100644
--- a/llvm/unittests/DWARFLinkerParallel/CMakeLists.txt
+++ b/llvm/unittests/DWARFLinkerParallel/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_unittest(DWARFLinkerParallelTests
   DWARFLinkerTest.cpp
   StringPoolTest.cpp
+  StringTableTest.cpp
   )
 
 target_link_libraries(DWARFLinkerParallelTests PRIVATE LLVMTestingSupport)

diff  --git a/llvm/unittests/DWARFLinkerParallel/StringTableTest.cpp b/llvm/unittests/DWARFLinkerParallel/StringTableTest.cpp
new file mode 100644
index 0000000000000..40795f5d38ae6
--- /dev/null
+++ b/llvm/unittests/DWARFLinkerParallel/StringTableTest.cpp
@@ -0,0 +1,104 @@
+//===- llvm/unittest/DWARFLinkerParallel/StringTableTest.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/DWARFLinkerParallel/StringTable.h"
+#include "llvm/Support/Parallel.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+using namespace llvm;
+using namespace dwarflinker_parallel;
+
+namespace {
+
+TEST(StringPoolTest, TestStringTable) {
+  struct StringDescription {
+    const char *Str = nullptr;
+    uint64_t Idx = 0;
+    uint64_t Offset = 0;
+  };
+
+  SmallVector<StringDescription> InputStrings = {
+      {"first", 0, 0}, {"second", 1, 6}, {"third", 2, 13}};
+
+  StringPool Strings;
+  StringTable OutStrings(Strings, nullptr);
+
+  // Check string insertion.
+  StringEntry *FirstPtr = Strings.insert(InputStrings[0].Str).first;
+  StringEntry *SecondPtr = Strings.insert(InputStrings[1].Str).first;
+  StringEntry *ThirdPtr = Strings.insert(InputStrings[2].Str).first;
+
+  FirstPtr = OutStrings.add(FirstPtr);
+  SecondPtr = OutStrings.add(SecondPtr);
+  ThirdPtr = OutStrings.add(ThirdPtr);
+
+  // Check fields of inserted strings.
+  EXPECT_TRUE(FirstPtr->getKey() == InputStrings[0].Str);
+  EXPECT_TRUE(FirstPtr->getValue()->Offset == InputStrings[0].Offset);
+  EXPECT_TRUE(FirstPtr->getValue()->Index == InputStrings[0].Idx);
+
+  EXPECT_TRUE(SecondPtr->getKey() == InputStrings[1].Str);
+  EXPECT_TRUE(SecondPtr->getValue()->Offset == InputStrings[1].Offset);
+  EXPECT_TRUE(SecondPtr->getValue()->Index == InputStrings[1].Idx);
+
+  EXPECT_TRUE(ThirdPtr->getKey() == InputStrings[2].Str);
+  EXPECT_TRUE(ThirdPtr->getValue()->Offset == InputStrings[2].Offset);
+  EXPECT_TRUE(ThirdPtr->getValue()->Index == InputStrings[2].Idx);
+
+  // Check order enumerated strings.
+  uint64_t CurIdx = 0;
+  std::function<void(DwarfStringPoolEntryRef)> checkStr =
+      [&](DwarfStringPoolEntryRef Entry) {
+        EXPECT_TRUE(Entry.getEntry().isIndexed());
+        EXPECT_TRUE(Entry.getIndex() == CurIdx);
+        EXPECT_TRUE(Entry.getOffset() == InputStrings[CurIdx].Offset);
+        EXPECT_TRUE(Entry.getString() == InputStrings[CurIdx].Str);
+
+        CurIdx++;
+      };
+
+  OutStrings.forEach(checkStr);
+}
+
+TEST(StringPoolTest, TestStringTableWithTranslator) {
+  std::string Word;
+  std::function<StringRef(StringRef)> TranslatorFunc =
+      [&](StringRef InputString) -> StringRef {
+    Word.clear();
+    for (auto Sym : InputString)
+      Word.insert(Word.begin(), Sym);
+    Word += '0';
+    return Word;
+  };
+
+  StringPool Strings;
+  StringTable OutStrings(Strings, TranslatorFunc);
+
+  StringEntry *FirstPtr = Strings.insert("first").first;
+  StringEntry *SecondPtr = Strings.insert("second").first;
+  StringEntry *ThirdPtr = Strings.insert("third").first;
+
+  FirstPtr = OutStrings.add(FirstPtr);
+  SecondPtr = OutStrings.add(SecondPtr);
+  ThirdPtr = OutStrings.add(ThirdPtr);
+
+  EXPECT_TRUE(FirstPtr->getKey() == "tsrif0");
+  EXPECT_TRUE(FirstPtr->getValue()->Offset == 0);
+  EXPECT_TRUE(FirstPtr->getValue()->Index == 0);
+
+  EXPECT_TRUE(SecondPtr->getKey() == "dnoces0");
+  EXPECT_TRUE(SecondPtr->getValue()->Offset == 7);
+  EXPECT_TRUE(SecondPtr->getValue()->Index == 1);
+
+  EXPECT_TRUE(ThirdPtr->getKey() == "driht0");
+  EXPECT_TRUE(ThirdPtr->getValue()->Offset == 15);
+  EXPECT_TRUE(ThirdPtr->getValue()->Index == 2);
+}
+
+} // anonymous namespace


        


More information about the llvm-commits mailing list