[PDB] Save one type record copy
authorReid Kleckner <rnk@google.com>
Tue, 4 Apr 2017 00:56:34 +0000 (00:56 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 4 Apr 2017 00:56:34 +0000 (00:56 +0000)
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

lld/COFF/PDB.cpp
llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp

index 79c798c..e32bcd2 100644 (file)
@@ -83,33 +83,22 @@ static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) {
 }
 
 static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
-                        codeview::TypeTableBuilder &TypeTable,
-                        std::vector<uint8_t> &Data) {
+                        codeview::TypeTableBuilder &TypeTable) {
   // Start the TPI or IPI stream header.
   TpiBuilder.setVersionHeader(pdb::PdbTpiV80);
 
   // Flatten the in memory type table.
-  // FIXME: Avoid this copy.
   TypeTable.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) {
-    Data.insert(Data.end(), Rec.begin(), Rec.end());
+    // FIXME: Hash types.
+    TpiBuilder.addTypeRecord(Rec, None);
   });
-
-  BinaryByteStream Stream(Data, support::little);
-  codeview::CVTypeArray Records;
-  BinaryStreamReader Reader(Stream);
-  if (auto EC = Reader.readArray(Records, Reader.getLength()))
-    fatal(EC, "Reader.readArray failed");
-  for (const codeview::CVType &Rec : Records)
-    TpiBuilder.addTypeRecord(Rec);
 }
 
 // Merge .debug$T sections into IpiData and TpiData.
 static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
-                        std::vector<uint8_t> &TpiData,
-                        std::vector<uint8_t> &IpiData) {
+                        codeview::TypeTableBuilder &TypeTable,
+                        codeview::TypeTableBuilder &IDTable) {
   // Visit all .debug$T sections to add them to Builder.
-  codeview::TypeTableBuilder IDTable(BAlloc);
-  codeview::TypeTableBuilder TypeTable(BAlloc);
   for (ObjectFile *File : Symtab->ObjectFiles) {
     ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
     if (Data.empty())
@@ -132,10 +121,10 @@ static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
   }
 
   // Construct TPI stream contents.
-  addTypeInfo(Builder.getTpiBuilder(), TypeTable, TpiData);
+  addTypeInfo(Builder.getTpiBuilder(), TypeTable);
 
   // Construct IPI stream contents.
-  addTypeInfo(Builder.getIpiBuilder(), IDTable, IpiData);
+  addTypeInfo(Builder.getIpiBuilder(), IDTable);
 }
 
 static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) {
@@ -213,9 +202,9 @@ void coff::createPDB(StringRef Path, SymbolTable *Symtab,
   auto &DbiBuilder = Builder.getDbiBuilder();
   DbiBuilder.setVersionHeader(pdb::PdbDbiV110);
 
-  std::vector<uint8_t> TpiData;
-  std::vector<uint8_t> IpiData;
-  mergeDebugT(Symtab, Builder, TpiData, IpiData);
+  codeview::TypeTableBuilder TypeTable(BAlloc);
+  codeview::TypeTableBuilder IDTable(BAlloc);
+  mergeDebugT(Symtab, Builder, TypeTable, IDTable);
 
   // Add Section Contributions.
   std::vector<pdb::SectionContrib> Contribs =
index fedd2e4..9fca26b 100644 (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;
 
index c34da58..27b9dad 100644 (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,
index 3bd5fd7..76d05c4 100644 (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));
 }