[PDB] Write FPO Data to the PDB.

llvm-svn: 342003
diff --git a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
index fd558aa..5881bf1 100644
--- a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
+++ b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp
@@ -14,8 +14,11 @@
 using namespace llvm::codeview;
 
 Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) {
-  if (auto EC = Reader.readObject(RelocPtr))
-    return EC;
+  if (Reader.bytesRemaining() % sizeof(FrameData) != 0) {
+    if (auto EC = Reader.readObject(RelocPtr))
+      return EC;
+  }
+
   if (Reader.bytesRemaining() % sizeof(FrameData) != 0)
     return make_error<CodeViewError>(cv_error_code::corrupt_record,
                                      "Invalid frame data record format!");
@@ -26,15 +29,30 @@
   return Error::success();
 }
 
+Error DebugFrameDataSubsectionRef::initialize(BinaryStreamRef Section) {
+  BinaryStreamReader Reader(Section);
+  return initialize(Reader);
+}
+
 uint32_t DebugFrameDataSubsection::calculateSerializedSize() const {
-  return 4 + sizeof(FrameData) * Frames.size();
+  uint32_t Size = sizeof(FrameData) * Frames.size();
+  if (IncludeRelocPtr)
+    Size += sizeof(uint32_t);
+  return Size;
 }
 
 Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const {
-  if (auto EC = Writer.writeInteger<uint32_t>(0))
-    return EC;
+  if (IncludeRelocPtr) {
+    if (auto EC = Writer.writeInteger<uint32_t>(0))
+      return EC;
+  }
 
-  if (auto EC = Writer.writeArray(makeArrayRef(Frames)))
+  std::vector<FrameData> SortedFrames(Frames.begin(), Frames.end());
+  std::sort(SortedFrames.begin(), SortedFrames.end(),
+            [](const FrameData &LHS, const FrameData &RHS) {
+              return LHS.RvaStart < RHS.RvaStart;
+            });
+  if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames)))
     return EC;
   return Error::success();
 }
diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index f6043bf..9b045f9 100644
--- a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
@@ -74,10 +75,23 @@
   PublicsStreamIndex = Index;
 }
 
+void DbiStreamBuilder::addFrameData(const codeview::FrameData &FD) {
+  if (!FrameData.hasValue())
+    FrameData.emplace(false);
+
+  FrameData->addFrameData(FD);
+}
+
 Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
                                      ArrayRef<uint8_t> Data) {
+  assert(Type != DbgHeaderType::NewFPO &&
+         "NewFPO data should be written via addFrameData()!");
+
   DbgStreams[(int)Type].emplace();
-  DbgStreams[(int)Type]->Data = Data;
+  DbgStreams[(int)Type]->Size = Data.size();
+  DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
+    return Writer.writeArray(Data);
+  };
   return Error::success();
 }
 
@@ -272,10 +286,20 @@
 }
 
 Error DbiStreamBuilder::finalizeMsfLayout() {
+  if (FrameData.hasValue()) {
+    DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
+    DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
+        FrameData->calculateSerializedSize();
+    DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
+        [this](BinaryStreamWriter &Writer) {
+          return FrameData->commit(Writer);
+        };
+  }
+
   for (auto &S : DbgStreams) {
     if (!S.hasValue())
       continue;
-    auto ExpectedIndex = Msf.addStream(S->Data.size());
+    auto ExpectedIndex = Msf.addStream(S->Size);
     if (!ExpectedIndex)
       return ExpectedIndex.takeError();
     S->StreamNumber = *ExpectedIndex;
@@ -406,7 +430,8 @@
     auto WritableStream = WritableMappedBlockStream::createIndexedStream(
         Layout, MsfBuffer, Stream->StreamNumber, Allocator);
     BinaryStreamWriter DbgStreamWriter(*WritableStream);
-    if (auto EC = DbgStreamWriter.writeArray(Stream->Data))
+
+    if (auto EC = Stream->WriteFn(DbgStreamWriter))
       return EC;
   }