blob: 86e5447179499d41563ba4dfaa00f84bc1035428 [file] [log] [blame]
Hans Wennborg83e6e1e2014-04-30 16:25:02 +00001//===-- 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
Rafael Espindola97de4742014-07-03 02:01:39 +000010#include "llvm/MC/StringTableBuilder.h"
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000011#include "llvm/ADT/SmallVector.h"
Rafael Espindola0169a452015-10-22 15:15:44 +000012#include "llvm/ADT/STLExtras.h"
Hans Wennborgf26bfc12014-09-29 22:43:20 +000013#include "llvm/Support/COFF.h"
14#include "llvm/Support/Endian.h"
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000015
16using namespace llvm;
17
Rafael Espindola0169a452015-10-22 15:15:44 +000018static int compareBySuffix(const StringRef *AP, const StringRef *BP) {
19 StringRef a = *AP;
20 StringRef b = *BP;
Akira Hatanaka8e77dbb2014-09-24 20:37:14 +000021 size_t sizeA = a.size();
22 size_t sizeB = b.size();
23 size_t len = std::min(sizeA, sizeB);
24 for (size_t i = 0; i < len; ++i) {
25 char ca = a[sizeA - i - 1];
26 char cb = b[sizeB - i - 1];
27 if (ca != cb)
Rafael Espindola0169a452015-10-22 15:15:44 +000028 return cb - ca;
Akira Hatanaka8e77dbb2014-09-24 20:37:14 +000029 }
Rafael Espindola0169a452015-10-22 15:15:44 +000030 return sizeB - sizeA;
Akira Hatanaka8e77dbb2014-09-24 20:37:14 +000031}
32
Hans Wennborgf26bfc12014-09-29 22:43:20 +000033void StringTableBuilder::finalize(Kind kind) {
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000034 SmallVector<StringRef, 8> Strings;
Hans Wennborgf26bfc12014-09-29 22:43:20 +000035 Strings.reserve(StringIndexMap.size());
36
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000037 for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i)
38 Strings.push_back(i->getKey());
39
Rafael Espindola0169a452015-10-22 15:15:44 +000040 array_pod_sort(Strings.begin(), Strings.end(), compareBySuffix);
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000041
Hans Wennborg1b1a3992014-10-06 17:05:19 +000042 switch (kind) {
43 case ELF:
44 case MachO:
Hans Wennborgf26bfc12014-09-29 22:43:20 +000045 // Start the table with a NUL byte.
46 StringTable += '\x00';
Hans Wennborg1b1a3992014-10-06 17:05:19 +000047 break;
48 case WinCOFF:
Hans Wennborgf26bfc12014-09-29 22:43:20 +000049 // Make room to write the table size later.
50 StringTable.append(4, '\x00');
Hans Wennborg1b1a3992014-10-06 17:05:19 +000051 break;
Hans Wennborgf26bfc12014-09-29 22:43:20 +000052 }
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000053
54 StringRef Previous;
55 for (StringRef s : Strings) {
Hans Wennborgf26bfc12014-09-29 22:43:20 +000056 if (kind == WinCOFF)
57 assert(s.size() > COFF::NameSize && "Short string in COFF string table!");
58
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000059 if (Previous.endswith(s)) {
60 StringIndexMap[s] = StringTable.size() - 1 - s.size();
61 continue;
62 }
63
64 StringIndexMap[s] = StringTable.size();
65 StringTable += s;
66 StringTable += '\x00';
67 Previous = s;
68 }
Hans Wennborgf26bfc12014-09-29 22:43:20 +000069
Hans Wennborg1b1a3992014-10-06 17:05:19 +000070 switch (kind) {
71 case ELF:
72 break;
73 case MachO:
74 // Pad to multiple of 4.
75 while (StringTable.size() % 4)
76 StringTable += '\x00';
77 break;
78 case WinCOFF:
79 // Write the table size in the first word.
Hans Wennborgf26bfc12014-09-29 22:43:20 +000080 assert(StringTable.size() <= std::numeric_limits<uint32_t>::max());
81 uint32_t size = static_cast<uint32_t>(StringTable.size());
82 support::endian::write<uint32_t, support::little, support::unaligned>(
83 StringTable.data(), size);
Hans Wennborg1b1a3992014-10-06 17:05:19 +000084 break;
Hans Wennborgf26bfc12014-09-29 22:43:20 +000085 }
86}
87
88void StringTableBuilder::clear() {
89 StringTable.clear();
90 StringIndexMap.clear();
Hans Wennborg83e6e1e2014-04-30 16:25:02 +000091}