[CodeView] Write CodeView line information.

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

llvm-svn: 301882
diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
index 8920dd9..41cb23a 100644
--- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -10,6 +10,7 @@
 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
 #include "llvm/DebugInfo/MSF/MSFCommon.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
@@ -35,11 +36,12 @@
 };
 }
 
-static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize) {
+static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
+                                            uint32_t C13Size) {
   uint32_t Size = sizeof(uint32_t); // Signature
   Size += SymbolByteSize;           // Symbol Data
-  Size += 0;                        // TODO: Layout.LineBytes
-  Size += 0;                        // TODO: Layout.C13Bytes
+  Size += 0;                        // TODO: Layout.C11Bytes
+  Size += C13Size;                  // C13 Debug Info Size
   Size += sizeof(uint32_t);         // GlobalRefs substream size (always 0)
   Size += 0;                        // GlobalRefs substream bytes
   return Size;
@@ -52,6 +54,8 @@
   Layout.Mod = ModIndex;
 }
 
+DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
+
 uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
   return Layout.ModDiStream;
 }
@@ -69,6 +73,15 @@
   SourceFiles.push_back(Path);
 }
 
+uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
+  uint32_t Result = 0;
+  for (const auto &Builder : C13Builders) {
+    assert(Builder && "Empty C13 Fragment Builder!");
+    Result += Builder->calculateSerializedLength();
+  }
+  return Result;
+}
+
 uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
   uint32_t L = sizeof(Layout);
   uint32_t M = ModuleName.size() + 1;
@@ -80,7 +93,7 @@
   Layout.FileNameOffs = 0; // TODO: Fix this
   Layout.Flags = 0;        // TODO: Fix this
   Layout.C11Bytes = 0;
-  Layout.C13Bytes = 0;
+  Layout.C13Bytes = calculateC13DebugInfoSize();
   (void)Layout.Mod;         // Set in constructor
   (void)Layout.ModDiStream; // Set in finalizeMsfLayout
   Layout.NumFiles = SourceFiles.size();
@@ -94,7 +107,9 @@
 
 Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
   this->Layout.ModDiStream = kInvalidStreamIndex;
-  auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize));
+  uint32_t C13Size = calculateC13DebugInfoSize();
+  auto ExpectedSN =
+      MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
   if (!ExpectedSN)
     return ExpectedSN.takeError();
   Layout.ModDiStream = *ExpectedSN;
@@ -130,7 +145,13 @@
     if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
       return EC;
     // TODO: Write C11 Line data
-    // TODO: Write C13 Line data
+
+    for (const auto &Builder : C13Builders) {
+      assert(Builder && "Empty C13 Fragment Builder!");
+      if (auto EC = Builder->commit(SymbolWriter))
+        return EC;
+    }
+
     // TODO: Figure out what GlobalRefs substream actually is and populate it.
     if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
       return EC;
@@ -139,3 +160,29 @@
   }
   return Error::success();
 }
+
+void DbiModuleDescriptorBuilder::addC13LineFragment(
+    std::unique_ptr<ModuleDebugLineFragment> Lines) {
+  ModuleDebugLineFragment &Frag = *Lines;
+
+  // File Checksums have to come first, so push an empty entry on if this
+  // is the first.
+  if (C13Builders.empty())
+    C13Builders.push_back(nullptr);
+
+  this->LineInfo.push_back(std::move(Lines));
+  C13Builders.push_back(
+      llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+}
+
+void DbiModuleDescriptorBuilder::setC13FileChecksums(
+    std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) {
+  assert(!ChecksumInfo && "Can't have more than one checksum info!");
+
+  if (C13Builders.empty())
+    C13Builders.push_back(nullptr);
+
+  ChecksumInfo = std::move(Checksums);
+  C13Builders[0] = llvm::make_unique<ModuleDebugFragmentRecordBuilder>(
+      ChecksumInfo->kind(), *ChecksumInfo);
+}