[PDB] Save one type record copy

Summary:
The TypeTableBuilder provides stable storage for type records. We don't
need to copy all of the bytes into a flat vector before adding it to the
TpiStreamBuilder.

This makes addTypeRecord take an ArrayRef<uint8_t> and a hash code to go
with it, which seems like a simplification.

Reviewers: ruiu, zturner, inglorion

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D31634

llvm-svn: 299406
This commit is contained in:
Reid Kleckner 2017-04-04 00:56:34 +00:00
parent 1a39114e26
commit adb3a08745
3 changed files with 25 additions and 21 deletions

View File

@ -53,7 +53,7 @@ public:
TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete;
void setVersionHeader(PdbRaw_TpiVer Version);
void addTypeRecord(const codeview::CVType &Record);
void addTypeRecord(ArrayRef<uint8_t> Type, Optional<uint32_t> Hash);
Error finalizeMsfLayout();
@ -68,9 +68,11 @@ private:
msf::MSFBuilder &Msf;
BumpPtrAllocator &Allocator;
size_t TypeRecordBytes = 0;
Optional<PdbRaw_TpiVer> VerHeader;
std::vector<codeview::CVType> TypeRecords;
BinaryItemStream<codeview::CVType> TypeRecordStream;
std::vector<ArrayRef<uint8_t>> TypeRecords;
std::vector<uint32_t> TypeHashes;
uint32_t HashStreamIndex = kInvalidStreamIndex;
std::unique_ptr<BinaryByteStream> HashValueStream;

View File

@ -34,8 +34,7 @@ using namespace llvm::pdb;
using namespace llvm::support;
TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
: Msf(Msf), Allocator(Msf.getAllocator()),
TypeRecordStream(llvm::support::little), Header(nullptr), Idx(StreamIdx) {
: Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
}
TpiStreamBuilder::~TpiStreamBuilder() = default;
@ -44,9 +43,12 @@ void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
VerHeader = Version;
}
void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) {
void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
Optional<uint32_t> Hash) {
TypeRecordBytes += Record.size();
TypeRecords.push_back(Record);
TypeRecordStream.setItems(TypeRecords);
if (Hash)
TypeHashes.push_back(*Hash);
}
Error TpiStreamBuilder::finalize() {
@ -62,7 +64,7 @@ Error TpiStreamBuilder::finalize() {
H->HeaderSize = sizeof(TpiStreamHeader);
H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
H->TypeIndexEnd = H->TypeIndexBegin + Count;
H->TypeRecordBytes = TypeRecordStream.getLength();
H->TypeRecordBytes = TypeRecordBytes;
H->HashStreamIndex = HashStreamIndex;
H->HashAuxStreamIndex = kInvalidStreamIndex;
@ -84,13 +86,13 @@ Error TpiStreamBuilder::finalize() {
}
uint32_t TpiStreamBuilder::calculateSerializedLength() {
return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
return sizeof(TpiStreamHeader) + TypeRecordBytes;
}
uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue())
return 0;
return TypeRecords.size() * sizeof(ulittle32_t);
assert(TypeHashes.size() == TypeHashes.size() &&
"either all or no type records should have hashes");
return TypeHashes.size() * sizeof(ulittle32_t);
}
Error TpiStreamBuilder::finalizeMsfLayout() {
@ -107,10 +109,10 @@ Error TpiStreamBuilder::finalizeMsfLayout() {
if (!ExpectedIndex)
return ExpectedIndex.takeError();
HashStreamIndex = *ExpectedIndex;
ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeRecords.size());
MutableArrayRef<ulittle32_t> HashBuffer(H, TypeRecords.size());
for (uint32_t I = 0; I < TypeRecords.size(); ++I) {
HashBuffer[I] = *TypeRecords[I].Hash % MinTpiHashBuckets;
ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size());
MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size());
for (uint32_t I = 0; I < TypeHashes.size(); ++I) {
HashBuffer[I] = TypeHashes[I] % MinTpiHashBuckets;
}
ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
HashBufferSize);
@ -131,9 +133,9 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
if (auto EC = Writer.writeObject(*Header))
return EC;
auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
if (auto EC = Writer.writeArray(RecordArray))
return EC;
for (auto Rec : TypeRecords)
if (auto EC = Writer.writeBytes(Rec))
return EC;
if (HashStreamIndex != kInvalidStreamIndex) {
auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,

View File

@ -436,13 +436,13 @@ static void yamlToPdb(StringRef Path) {
const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
TpiBuilder.setVersionHeader(Tpi.Version);
for (const auto &R : Tpi.Records)
TpiBuilder.addTypeRecord(R.Record);
TpiBuilder.addTypeRecord(R.Record.data(), R.Record.Hash);
const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultTpiStream);
auto &IpiBuilder = Builder.getIpiBuilder();
IpiBuilder.setVersionHeader(Ipi.Version);
for (const auto &R : Ipi.Records)
IpiBuilder.addTypeRecord(R.Record);
TpiBuilder.addTypeRecord(R.Record.data(), R.Record.Hash);
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
}