forked from OSchip/llvm-project
Add a RAW mode to StringTableBuilder.
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. llvm-svn: 251153
This commit is contained in:
parent
803195ed6d
commit
21956e4007
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue