[CodeView] Write CodeView line information.

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

llvm-svn: 301882
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
index eec0793..833cd81 100644
--- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
@@ -89,11 +89,11 @@
     DictScope DD(P, "Lines");
 
     for (const auto &Fragment : Lines) {
-      DictScope DDD(P, "LineFragment");
+      DictScope DDD(P, "Block");
       P.printNumber("RelocSegment", Fragment.header()->RelocSegment);
       P.printNumber("RelocOffset", Fragment.header()->RelocOffset);
       P.printNumber("CodeSize", Fragment.header()->CodeSize);
-      P.printNumber("HasColumns", Fragment.hasColumnInfo());
+      P.printBoolean("HasColumns", Fragment.hasColumnInfo());
 
       for (const auto &L : Fragment) {
         DictScope DDDD(P, "Lines");
@@ -557,6 +557,7 @@
 
   bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
   if (IsSilentDatabaseBuild) {
+    outs().flush();
     errs() << "Building Type Information For " << Label << "\n";
   }
 
diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
index 770d227..18596a6 100644
--- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
@@ -286,8 +286,7 @@
         continue;
 
       auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
-          File.getMsfLayout(), File.getMsfBuffer(),
-          MI.Info.getModuleStreamIndex());
+          File.getMsfLayout(), File.getMsfBuffer(), ModiStream);
 
       pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData));
       if (auto EC = ModS.reload())
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index e6d363e..0bbc49e 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -28,6 +28,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/config.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
@@ -491,6 +492,67 @@
       for (auto Symbol : ModiStream.Symbols)
         ModiBuilder.addSymbol(Symbol.Record);
     }
+    if (MI.FileLineInfo.hasValue()) {
+      const auto &FLI = *MI.FileLineInfo;
+
+      // File Checksums must be emitted before line information, because line
+      // info records use offsets into the checksum buffer to reference a file's
+      // source file name.
+      auto Checksums = llvm::make_unique<ModuleDebugFileChecksumFragment>();
+      auto &ChecksumRef = *Checksums;
+      if (!FLI.FileChecksums.empty()) {
+        auto &Strings = Builder.getStringTableBuilder();
+        for (auto &FC : FLI.FileChecksums) {
+          uint32_t STOffset = Strings.getStringIndex(FC.FileName);
+          Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes);
+        }
+      }
+      ModiBuilder.setC13FileChecksums(std::move(Checksums));
+
+      for (const auto &Fragment : FLI.LineFragments) {
+        auto Lines = llvm::make_unique<ModuleDebugLineFragment>();
+        Lines->setCodeSize(Fragment.CodeSize);
+        Lines->setRelocationAddress(Fragment.RelocSegment,
+                                    Fragment.RelocOffset);
+        Lines->setFlags(Fragment.Flags);
+        for (const auto &LC : Fragment.Blocks) {
+          // FIXME: StringTable / StringTableBuilder should really be in
+          // DebugInfoCodeView.  This would allow us to construct the
+          // ModuleDebugLineFragment with a reference to the string table,
+          // and we could just pass strings around rather than having to
+          // remember how to calculate the right offset.
+          auto &Strings = Builder.getStringTableBuilder();
+          // The offset in the line info record is the offset of the checksum
+          // entry for the corresponding file.  That entry then contains an
+          // offset into the global string table of the file name.  So to
+          // compute the proper offset to write into the line info record, we
+          // must first get its offset in the global string table, then ask the
+          // checksum builder to find the offset in its serialized buffer that
+          // it mapped that filename string table offset to.
+          uint32_t StringOffset = Strings.getStringIndex(LC.FileName);
+          uint32_t ChecksumOffset = ChecksumRef.mapChecksumOffset(StringOffset);
+
+          Lines->createBlock(ChecksumOffset);
+          if (Lines->hasColumnInfo()) {
+            for (const auto &Item : zip(LC.Lines, LC.Columns)) {
+              auto &L = std::get<0>(Item);
+              auto &C = std::get<1>(Item);
+              uint32_t LE = L.LineStart + L.EndDelta;
+              Lines->addLineAndColumnInfo(
+                  L.Offset, LineInfo(L.LineStart, LE, L.IsStatement),
+                  C.StartColumn, C.EndColumn);
+            }
+          } else {
+            for (const auto &L : LC.Lines) {
+              uint32_t LE = L.LineStart + L.EndDelta;
+              Lines->addLineInfo(L.Offset,
+                                 LineInfo(L.LineStart, LE, L.IsStatement));
+            }
+          }
+        }
+        ModiBuilder.addC13LineFragment(std::move(Lines));
+      }
+    }
   }
 
   auto &TpiBuilder = Builder.getTpiBuilder();