[pdb] Round trip the PDB stream between YAML and binary PDB.

This gets writing of the PDB stream working.

llvm-svn: 274647
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
index cf0ef68..2d8e0d0 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
@@ -89,7 +89,7 @@
     return make_error<RawError>(
         raw_error_code::invalid_block_address,
         "setBlockData attempted to write out of block bounds.");
-  if (Data.size() >= getBlockSize() - Offset)
+  if (Data.size() > getBlockSize() - Offset)
     return make_error<RawError>(
         raw_error_code::invalid_block_address,
         "setBlockData attempted to write out of block bounds.");
@@ -167,6 +167,17 @@
   return DirectoryBlocks;
 }
 
+Expected<InfoStream &> PDBFile::emplacePDBInfoStream() {
+  if (Info)
+    Info.reset();
+
+  auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
+  if (!InfoS)
+    return InfoS.takeError();
+  Info = llvm::make_unique<InfoStream>(std::move(*InfoS));
+  return *Info;
+}
+
 Expected<InfoStream &> PDBFile::getPDBInfoStream() {
   if (!Info) {
     auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
@@ -340,12 +351,59 @@
 }
 
 void PDBFile::setStreamMap(
-    ArrayRef<support::ulittle32_t> Directory,
     std::vector<ArrayRef<support::ulittle32_t>> &Streams) {
-  DirectoryBlocks = Directory;
   StreamMap = Streams;
 }
 
+void PDBFile::setDirectoryBlocks(ArrayRef<support::ulittle32_t> Directory) {
+  DirectoryBlocks = Directory;
+}
+
+Error PDBFile::generateSimpleStreamMap() {
+  if (StreamSizes.empty())
+    return Error::success();
+
+  static std::vector<std::vector<support::ulittle32_t>> StaticMap;
+  StreamMap.clear();
+  StaticMap.clear();
+
+  // Figure out how many blocks are needed for all streams, and set the first
+  // used block to the highest block so that we can write the rest of the
+  // blocks contiguously.
+  uint32_t TotalFileBlocks = getBlockCount();
+  std::vector<support::ulittle32_t> ReservedBlocks;
+  ReservedBlocks.push_back(support::ulittle32_t(0));
+  ReservedBlocks.push_back(SB->BlockMapAddr);
+  ReservedBlocks.insert(ReservedBlocks.end(), DirectoryBlocks.begin(),
+                        DirectoryBlocks.end());
+
+  uint32_t BlocksNeeded = 0;
+  for (auto Size : StreamSizes)
+    BlocksNeeded += bytesToBlocks(Size, getBlockSize());
+
+  support::ulittle32_t NextBlock(TotalFileBlocks - BlocksNeeded -
+                                 ReservedBlocks.size());
+
+  StaticMap.resize(StreamSizes.size());
+  for (uint32_t S = 0; S < StreamSizes.size(); ++S) {
+    uint32_t Size = StreamSizes[S];
+    uint32_t NumBlocks = bytesToBlocks(Size, getBlockSize());
+    auto &ThisStream = StaticMap[S];
+    for (uint32_t I = 0; I < NumBlocks;) {
+      NextBlock += 1;
+      if (std::find(ReservedBlocks.begin(), ReservedBlocks.end(), NextBlock) !=
+          ReservedBlocks.end())
+        continue;
+
+      ++I;
+      assert(NextBlock < getBlockCount());
+      ThisStream.push_back(NextBlock);
+    }
+    StreamMap.push_back(ThisStream);
+  }
+  return Error::success();
+}
+
 Error PDBFile::commit() {
   StreamWriter Writer(*Buffer);
 
@@ -371,5 +429,35 @@
       return EC;
   }
 
+  if (Info) {
+    if (auto EC = Info->commit())
+      return EC;
+  }
+
+  if (Dbi) {
+    if (auto EC = Dbi->commit())
+      return EC;
+  }
+
+  if (Symbols) {
+    if (auto EC = Symbols->commit())
+      return EC;
+  }
+
+  if (Publics) {
+    if (auto EC = Publics->commit())
+      return EC;
+  }
+
+  if (Tpi) {
+    if (auto EC = Tpi->commit())
+      return EC;
+  }
+
+  if (Ipi) {
+    if (auto EC = Ipi->commit())
+      return EC;
+  }
+
   return Buffer->commit();
 }
\ No newline at end of file