StringTableBuilder.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //===-- StringTableBuilder.cpp - String table building utility ------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/MC/StringTableBuilder.h"
  10. #include "llvm/ADT/SmallVector.h"
  11. #include "llvm/Support/COFF.h"
  12. #include "llvm/Support/Endian.h"
  13. using namespace llvm;
  14. static bool compareBySuffix(StringRef a, StringRef b) {
  15. size_t sizeA = a.size();
  16. size_t sizeB = b.size();
  17. size_t len = std::min(sizeA, sizeB);
  18. for (size_t i = 0; i < len; ++i) {
  19. char ca = a[sizeA - i - 1];
  20. char cb = b[sizeB - i - 1];
  21. if (ca != cb)
  22. return ca > cb;
  23. }
  24. return sizeA > sizeB;
  25. }
  26. void StringTableBuilder::finalize(Kind kind) {
  27. SmallVector<StringRef, 8> Strings;
  28. Strings.reserve(StringIndexMap.size());
  29. for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i)
  30. Strings.push_back(i->getKey());
  31. std::sort(Strings.begin(), Strings.end(), compareBySuffix);
  32. switch (kind) {
  33. case ELF:
  34. case MachO:
  35. // Start the table with a NUL byte.
  36. StringTable += '\x00';
  37. break;
  38. case WinCOFF:
  39. // Make room to write the table size later.
  40. StringTable.append(4, '\x00');
  41. break;
  42. }
  43. StringRef Previous;
  44. for (StringRef s : Strings) {
  45. if (kind == WinCOFF)
  46. assert(s.size() > COFF::NameSize && "Short string in COFF string table!");
  47. if (Previous.endswith(s)) {
  48. StringIndexMap[s] = StringTable.size() - 1 - s.size();
  49. continue;
  50. }
  51. StringIndexMap[s] = StringTable.size();
  52. StringTable += s;
  53. StringTable += '\x00';
  54. Previous = s;
  55. }
  56. switch (kind) {
  57. case ELF:
  58. break;
  59. case MachO:
  60. // Pad to multiple of 4.
  61. while (StringTable.size() % 4)
  62. StringTable += '\x00';
  63. break;
  64. case WinCOFF:
  65. // Write the table size in the first word.
  66. assert(StringTable.size() <= std::numeric_limits<uint32_t>::max());
  67. uint32_t size = static_cast<uint32_t>(StringTable.size());
  68. support::endian::write<uint32_t, support::little, support::unaligned>(
  69. StringTable.data(), size);
  70. break;
  71. }
  72. }
  73. void StringTableBuilder::clear() {
  74. StringTable.clear();
  75. StringIndexMap.clear();
  76. }