Add a RAW mode to StringTableBuilder.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 23 Oct 2015 21:48:05 +0000 (21:48 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 23 Oct 2015 21:48:05 +0000 (21:48 +0000)
In this mode it just tries to tail merge the strings without imposing any other
format constrains. It will not, for example, add a null byte between them.

Also add support for keeping a tentative size and offset if we decide to
not optimize after all.

This will be used shortly in lld for merging SHF_STRINGS sections.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251153 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCMachObjectWriter.h
include/llvm/MC/StringTableBuilder.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MachObjectWriter.cpp
lib/MC/StringTableBuilder.cpp
lib/MC/WinCOFFObjectWriter.cpp
tools/yaml2obj/yaml2elf.cpp
unittests/MC/StringTableBuilderTest.cpp

index fe1227fe3dd92d141d19eec086cfb2c73152c49c..730b0e4d83a58a2b9daebfc40c24112a6d225d45 100644 (file)
@@ -104,7 +104,7 @@ class MachObjectWriter : public MCObjectWriter {
   /// \name Symbol Table Data
   /// @{
 
-  StringTableBuilder StringTable;
+  StringTableBuilder StringTable{StringTableBuilder::MachO};
   std::vector<MachSymbolData> LocalSymbolData;
   std::vector<MachSymbolData> ExternalSymbolData;
   std::vector<MachSymbolData> UndefinedSymbolData;
index 68ad76e7fae9e48f156df45f0836c9d9aabfe88e..adde86b455830773fd3325f1bc6bafbd99caa50f 100644 (file)
@@ -18,23 +18,26 @@ namespace llvm {
 
 /// \brief Utility for building string tables with deduplicated suffixes.
 class StringTableBuilder {
+public:
+  enum Kind { ELF, WinCOFF, MachO, RAW };
+
+private:
   SmallString<256> StringTable;
   DenseMap<StringRef, size_t> StringIndexMap;
+  size_t Size = 0;
+  Kind K;
 
 public:
-  /// \brief Add a string to the builder. Returns a StringRef to the internal
-  /// copy of s. Can only be used before the table is finalized.
-  void add(StringRef S);
+  StringTableBuilder(Kind K);
 
-  enum Kind {
-    ELF,
-    WinCOFF,
-    MachO
-  };
+  /// \brief Add a string to the builder. Returns the position of S in the
+  /// table. The position will be changed if finalize is used.
+  /// Can only be used before the table is finalized.
+  size_t add(StringRef S);
 
   /// \brief Analyze the strings and build the final table. No more strings can
   /// be added after this point.
-  void finalize(Kind K);
+  void finalize();
 
   /// \brief Retrieve the string table data. Can only be used after the table
   /// is finalized.
@@ -47,6 +50,8 @@ public:
   /// after the table is finalized.
   size_t getOffset(StringRef S) const;
 
+  const DenseMap<StringRef, size_t> &getMap() const { return StringIndexMap; }
+  size_t getSize() const { return Size; }
   void clear();
 
 private:
index 5fdfcf9ef2de8c751a90abb052b8365958ff424f..230d3d775b13be775f2db4a5dc93187401dc1a3d 100644 (file)
@@ -109,7 +109,7 @@ class ELFObjectWriter : public MCObjectWriter {
 
     BumpPtrAllocator Alloc;
     StringSaver VersionSymSaver{Alloc};
-    StringTableBuilder StrTabBuilder;
+    StringTableBuilder StrTabBuilder{StringTableBuilder::ELF};
 
     /// @}
 
@@ -880,7 +880,7 @@ void ELFObjectWriter::computeSymbolTable(
   for (const std::string &Name : FileNames)
     StrTabBuilder.add(Name);
 
-  StrTabBuilder.finalize(StringTableBuilder::ELF);
+  StrTabBuilder.finalize();
 
   for (const std::string &Name : FileNames)
     Writer.writeSymbol(StrTabBuilder.getOffset(Name),
index d5184f1d9a48d9dd26341221339f8960522d0d89..17023d82d6277d921655f2e6d3180c1830d925e9 100644 (file)
@@ -520,7 +520,7 @@ void MachObjectWriter::computeSymbolTable(
 
     StringTable.add(Symbol.getName());
   }
-  StringTable.finalize(StringTableBuilder::MachO);
+  StringTable.finalize();
 
   // Build the symbol arrays but only for non-local symbols.
   //
index fc6c3bc09021e0b58b9c76383a57bda75a96d9f7..6210238e72a587281f25881ff88301acfb499283 100644 (file)
@@ -16,6 +16,8 @@
 
 using namespace llvm;
 
+StringTableBuilder::StringTableBuilder(Kind K) : K(K) {}
+
 static int compareBySuffix(std::pair<StringRef, size_t> *const *AP,
                            std::pair<StringRef, size_t> *const *BP) {
   StringRef A = (*AP)->first;
@@ -32,7 +34,7 @@ static int compareBySuffix(std::pair<StringRef, size_t> *const *AP,
   return SizeB - SizeA;
 }
 
-void StringTableBuilder::finalize(Kind K) {
+void StringTableBuilder::finalize() {
   std::vector<std::pair<StringRef, size_t> *> Strings;
   Strings.reserve(StringIndexMap.size());
   for (std::pair<StringRef, size_t> &P : StringIndexMap)
@@ -41,6 +43,8 @@ void StringTableBuilder::finalize(Kind K) {
   array_pod_sort(Strings.begin(), Strings.end(), compareBySuffix);
 
   switch (K) {
+  case RAW:
+    break;
   case ELF:
   case MachO:
     // Start the table with a NUL byte.
@@ -59,17 +63,19 @@ void StringTableBuilder::finalize(Kind K) {
       assert(S.size() > COFF::NameSize && "Short string in COFF string table!");
 
     if (Previous.endswith(S)) {
-      P->second = StringTable.size() - 1 - S.size();
+      P->second = StringTable.size() - S.size() - (K != RAW);
       continue;
     }
 
     P->second = StringTable.size();
     StringTable += S;
-    StringTable += '\x00';
+    if (K != RAW)
+      StringTable += '\x00';
     Previous = S;
   }
 
   switch (K) {
+  case RAW:
   case ELF:
     break;
   case MachO:
@@ -85,6 +91,8 @@ void StringTableBuilder::finalize(Kind K) {
         StringTable.data(), Size);
     break;
   }
+
+  Size = StringTable.size();
 }
 
 void StringTableBuilder::clear() {
@@ -99,7 +107,10 @@ size_t StringTableBuilder::getOffset(StringRef S) const {
   return I->second;
 }
 
-void StringTableBuilder::add(StringRef S) {
+size_t StringTableBuilder::add(StringRef S) {
   assert(!isFinalized());
-  StringIndexMap.insert(std::make_pair(S, 0));
+  auto P = StringIndexMap.insert(std::make_pair(S, Size));
+  if (P.second)
+    Size += S.size() + (K != RAW);
+  return P.first->second;
 }
index f251942161d81bc2801fc72d0433c655044e62cb..8d4d3df21ab48b959b2b4e0562a9a502046851ed 100644 (file)
@@ -127,7 +127,7 @@ public:
   COFF::header Header;
   sections Sections;
   symbols Symbols;
-  StringTableBuilder Strings;
+  StringTableBuilder Strings{StringTableBuilder::WinCOFF};
 
   // Maps used during object file creation.
   section_map SectionMap;
@@ -908,7 +908,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
   for (const auto &S : Symbols)
     if (S->should_keep() && S->Name.size() > COFF::NameSize)
       Strings.add(S->Name);
-  Strings.finalize(StringTableBuilder::WinCOFF);
+  Strings.finalize();
 
   // Set names.
   for (const auto &S : Sections)
index 849f202b126a5e73521ecc5f0ecc2091270a50ff..d03986e9c88d5aa61219ad74b7af406ce3a44d22 100644 (file)
@@ -105,10 +105,10 @@ class ELFState {
   typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
 
   /// \brief The future ".strtab" section.
-  StringTableBuilder DotStrtab;
+  StringTableBuilder DotStrtab{StringTableBuilder::ELF};
 
   /// \brief The future ".shstrtab" section.
-  StringTableBuilder DotShStrtab;
+  StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
 
   NameToIdxMap SN2I;
   NameToIdxMap SymN2I;
@@ -193,7 +193,7 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
 
   for (const auto &Sec : Doc.Sections)
     DotShStrtab.add(Sec->Name);
-  DotShStrtab.finalize(StringTableBuilder::ELF);
+  DotShStrtab.finalize();
 
   for (const auto &Sec : Doc.Sections) {
     zero(SHeader);
@@ -286,7 +286,7 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
     DotStrtab.add(Sym.Name);
   for (const auto &Sym : Doc.Symbols.Weak)
     DotStrtab.add(Sym.Name);
-  DotStrtab.finalize(StringTableBuilder::ELF);
+  DotStrtab.finalize();
 
   addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
   addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
index 716b9c7ae879985ea1a3858a59913df67766f320..4cc0bda0a03ac10ffe5ef3f1f8ee8a0abfaf8d68 100644 (file)
@@ -17,13 +17,13 @@ using namespace llvm;
 namespace {
 
 TEST(StringTableBuilderTest, BasicELF) {
-  StringTableBuilder B;
+  StringTableBuilder B(StringTableBuilder::ELF);
 
   B.add("foo");
   B.add("bar");
   B.add("foobar");
 
-  B.finalize(StringTableBuilder::ELF);
+  B.finalize();
 
   std::string Expected;
   Expected += '\x00';
@@ -39,14 +39,14 @@ TEST(StringTableBuilderTest, BasicELF) {
 }
 
 TEST(StringTableBuilderTest, BasicWinCOFF) {
-  StringTableBuilder B;
+  StringTableBuilder B(StringTableBuilder::WinCOFF);
 
   // Strings must be 9 chars or longer to go in the table.
   B.add("hippopotamus");
   B.add("pygmy hippopotamus");
   B.add("river horse");
 
-  B.finalize(StringTableBuilder::WinCOFF);
+  B.finalize();
 
   // size_field + "pygmy hippopotamus\0" + "river horse\0"
   uint32_t ExpectedSize = 4 + 19 + 12;