llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
Zachary Turner c504ae3cef Resubmit r301986 and r301987 "Add codeview::StringTable"
This was reverted due to a "missing" file, but in reality
what happened was that I renamed a file, and then due to
a merge conflict both the old file and the new file got
added to the repository.  This led to an unused cpp file
being in the repo and not referenced by any CMakeLists.txt
but #including a .h file that wasn't in the repo.  In an
even more unfortunate coincidence, CMake didn't report the
unused cpp file because it was in a subdirectory of the
folder with the CMakeLists.txt, and not in the same directory
as any CMakeLists.txt.

The presence of the unused file was then breaking certain
tools that determine file lists by globbing rather than
by what's specified in CMakeLists.txt

In any case, the fix is to just remove the unused file from
the patch set.

llvm-svn: 302042
2017-05-03 15:58:37 +00:00

134 lines
4.2 KiB
C++

//===- PDBStringTableBuilder.cpp - PDB String Table -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/Hash.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
using namespace llvm;
using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::support::endian;
using namespace llvm::pdb;
uint32_t PDBStringTableBuilder::insert(StringRef S) {
return Strings.insert(S);
}
static uint32_t computeBucketCount(uint32_t NumStrings) {
// The /names stream is basically an on-disk open-addressing hash table.
// Hash collisions are resolved by linear probing. We cannot make
// utilization 100% because it will make the linear probing extremely
// slow. But lower utilization wastes disk space. As a reasonable
// load factor, we choose 80%. We need +1 because slot 0 is reserved.
return (NumStrings + 1) * 1.25;
}
uint32_t PDBStringTableBuilder::calculateHashTableSize() const {
uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field.
Size += sizeof(uint32_t) * computeBucketCount(Strings.size());
return Size;
}
uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
uint32_t Size = 0;
Size += sizeof(PDBStringTableHeader);
Size += Strings.calculateSerializedSize();
Size += calculateHashTableSize();
Size += sizeof(uint32_t); // The /names stream ends with the string count.
return Size;
}
Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
// Write a header
PDBStringTableHeader H;
H.Signature = PDBStringTableSignature;
H.HashVersion = 1;
H.ByteSize = Strings.calculateSerializedSize();
if (auto EC = Writer.writeObject(H))
return EC;
assert(Writer.bytesRemaining() == 0);
return Error::success();
}
Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const {
if (auto EC = Strings.commit(Writer))
return EC;
assert(Writer.bytesRemaining() == 0);
return Error::success();
}
Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
// Write a hash table.
uint32_t BucketCount = computeBucketCount(Strings.size());
if (auto EC = Writer.writeInteger(BucketCount))
return EC;
std::vector<ulittle32_t> Buckets(BucketCount);
for (auto &Pair : Strings) {
StringRef S = Pair.getKey();
uint32_t Offset = Pair.getValue();
uint32_t Hash = hashStringV1(S);
for (uint32_t I = 0; I != BucketCount; ++I) {
uint32_t Slot = (Hash + I) % BucketCount;
if (Slot == 0)
continue; // Skip reserved slot
if (Buckets[Slot] != 0)
continue;
Buckets[Slot] = Offset;
break;
}
}
if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
return EC;
assert(Writer.bytesRemaining() == 0);
return Error::success();
}
Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const {
if (auto EC = Writer.writeInteger<uint32_t>(Strings.size()))
return EC;
assert(Writer.bytesRemaining() == 0);
return Error::success();
}
Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
BinaryStreamWriter SectionWriter;
std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader));
if (auto EC = writeHeader(SectionWriter))
return EC;
std::tie(SectionWriter, Writer) =
Writer.split(Strings.calculateSerializedSize());
if (auto EC = writeStrings(SectionWriter))
return EC;
std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize());
if (auto EC = writeHashTable(SectionWriter))
return EC;
std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t));
if (auto EC = writeEpilogue(SectionWriter))
return EC;
return Error::success();
}