[llvm] r301882 - [CodeView] Write CodeView line information.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Mon May 1 16:27:42 PDT 2017


Author: zturner
Date: Mon May  1 18:27:42 2017
New Revision: 301882

URL: http://llvm.org/viewvc/llvm-project?rev=301882&view=rev
Log:
[CodeView] Write CodeView line information.

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

Added:
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.h
    llvm/trunk/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp
    llvm/trunk/test/DebugInfo/PDB/Inputs/simple-line-info.yaml
    llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h
    llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp
    llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp
    llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp
    llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp
    llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h Mon May  1 18:27:42 2017
@@ -11,7 +11,9 @@
 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
+#include "llvm/Support/Allocator.h"
 #include "llvm/Support/BinaryStreamArray.h"
 #include "llvm/Support/BinaryStreamReader.h"
 #include "llvm/Support/Endian.h"
@@ -61,6 +63,28 @@ public:
 private:
   FileChecksumArray Checksums;
 };
+
+class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment {
+public:
+  ModuleDebugFileChecksumFragment();
+
+  static bool classof(const ModuleDebugFragment *S) {
+    return S->kind() == ModuleDebugFragmentKind::FileChecksums;
+  }
+
+  void addChecksum(uint32_t StringTableOffset, FileChecksumKind Kind,
+                   ArrayRef<uint8_t> Bytes);
+
+  uint32_t calculateSerializedLength() override;
+  Error commit(BinaryStreamWriter &Writer) override;
+  uint32_t mapChecksumOffset(uint32_t StringTableOffset) const;
+
+private:
+  DenseMap<uint32_t, uint32_t> OffsetMap;
+  uint32_t SerializedSize = 0;
+  llvm::BumpPtrAllocator Storage;
+  std::vector<FileChecksumEntry> Checksums;
+};
 }
 }
 

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h Mon May  1 18:27:42 2017
@@ -11,6 +11,7 @@
 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H
 
 #include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/Support/BinaryStreamWriter.h"
 #include "llvm/Support/Casting.h"
 
 namespace llvm {
@@ -25,6 +26,20 @@ public:
 
 protected:
   ModuleDebugFragmentKind Kind;
+};
+
+class ModuleDebugFragment {
+public:
+  explicit ModuleDebugFragment(ModuleDebugFragmentKind Kind) : Kind(Kind) {}
+  virtual ~ModuleDebugFragment();
+
+  ModuleDebugFragmentKind kind() const { return Kind; }
+
+  virtual Error commit(BinaryStreamWriter &Writer) = 0;
+  virtual uint32_t calculateSerializedLength() = 0;
+
+protected:
+  ModuleDebugFragmentKind Kind;
 };
 
 } // namespace codeview

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h Mon May  1 18:27:42 2017
@@ -13,12 +13,15 @@
 #include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/Support/BinaryStreamArray.h"
 #include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryStreamWriter.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 
 namespace llvm {
 namespace codeview {
 
+class ModuleDebugFragment;
+
 // Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
 struct ModuleDebugFragmentHeader {
   support::ulittle32_t Kind;   // codeview::ModuleDebugFragmentKind enum
@@ -32,6 +35,7 @@ public:
 
   static Error initialize(BinaryStreamRef Stream,
                           ModuleDebugFragmentRecord &Info);
+
   uint32_t getRecordLength() const;
   ModuleDebugFragmentKind kind() const;
   BinaryStreamRef getRecordData() const;
@@ -41,6 +45,18 @@ private:
   BinaryStreamRef Data;
 };
 
+class ModuleDebugFragmentRecordBuilder {
+public:
+  ModuleDebugFragmentRecordBuilder(ModuleDebugFragmentKind Kind,
+                                   ModuleDebugFragment &Frag);
+  uint32_t calculateSerializedLength();
+  Error commit(BinaryStreamWriter &Writer);
+
+private:
+  ModuleDebugFragmentKind Kind;
+  ModuleDebugFragment &Frag;
+};
+
 typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray;
 
 } // namespace codeview

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h Mon May  1 18:27:42 2017
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
 #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
 
+#include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
 #include "llvm/Support/BinaryStreamArray.h"
 #include "llvm/Support/BinaryStreamReader.h"
@@ -28,7 +29,10 @@ struct LineFragmentHeader {
 
 // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
 struct LineBlockFragmentHeader {
-  support::ulittle32_t NameIndex; // Index in DBI name buffer of filename.
+  support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File
+                                  // checksums buffer.  The checksum entry then
+                                  // contains another offset into the string
+                                  // table of the actual name.
   support::ulittle32_t NumLines;  // Number of lines
   support::ulittle32_t BlockSize; // Code size of block, in bytes.
   // The following two variable length arrays appear immediately after the
@@ -88,6 +92,45 @@ private:
   const LineFragmentHeader *Header = nullptr;
   LineInfoArray LinesAndColumns;
 };
+
+class ModuleDebugLineFragment final : public ModuleDebugFragment {
+  struct Block {
+    Block(uint32_t ChecksumBufferOffset)
+        : ChecksumBufferOffset(ChecksumBufferOffset) {}
+
+    uint32_t ChecksumBufferOffset;
+    std::vector<LineNumberEntry> Lines;
+    std::vector<ColumnNumberEntry> Columns;
+  };
+
+public:
+  ModuleDebugLineFragment();
+
+  static bool classof(const ModuleDebugFragment *S) {
+    return S->kind() == ModuleDebugFragmentKind::Lines;
+  }
+
+  void createBlock(uint32_t ChecksumBufferOffset);
+  void addLineInfo(uint32_t Offset, const LineInfo &Line);
+  void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line,
+                            uint32_t ColStart, uint32_t ColEnd);
+
+  uint32_t calculateSerializedLength() override;
+  Error commit(BinaryStreamWriter &Writer) override;
+
+  void setRelocationAddress(uint16_t Segment, uint16_t Offset);
+  void setCodeSize(uint32_t Size);
+  void setFlags(LineFlags Flags);
+
+  bool hasColumnInfo() const;
+
+private:
+  uint16_t RelocOffset = 0;
+  uint16_t RelocSegment = 0;
+  uint32_t CodeSize = 0;
+  LineFlags Flags = LF_None;
+  std::vector<Block> Blocks;
+};
 }
 }
 

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h Mon May  1 18:27:42 2017
@@ -35,6 +35,7 @@ public:
   StringRef getTypeName(TypeIndex Index) const;
 
   const CVType &getTypeRecord(TypeIndex Index) const;
+  CVType &getTypeRecord(TypeIndex Index);
 
   bool containsTypeIndex(TypeIndex Index) const;
 

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h Mon May  1 18:27:42 2017
@@ -11,6 +11,8 @@
 #define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
 #include "llvm/Support/Error.h"
@@ -21,6 +23,10 @@
 namespace llvm {
 class BinaryStreamWriter;
 
+namespace codeview {
+class ModuleDebugFragmentRecordBuilder;
+}
+
 namespace msf {
 class MSFBuilder;
 struct MSFLayout;
@@ -33,6 +39,7 @@ class DbiModuleDescriptorBuilder {
 public:
   DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex,
                              msf::MSFBuilder &Msf);
+  ~DbiModuleDescriptorBuilder();
 
   DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete;
   DbiModuleDescriptorBuilder &
@@ -41,6 +48,11 @@ public:
   void setObjFileName(StringRef Name);
   void addSymbol(codeview::CVSymbol Symbol);
 
+  void
+  addC13LineFragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
+  void setC13FileChecksums(
+      std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> Checksums);
+
   uint16_t getStreamIndex() const;
   StringRef getModuleName() const { return ModuleName; }
   StringRef getObjFileName() const { return ObjFileName; }
@@ -58,6 +70,8 @@ public:
                WritableBinaryStreamRef MsfBuffer);
 
 private:
+  uint32_t calculateC13DebugInfoSize() const;
+
   void addSourceFile(StringRef Path);
   msf::MSFBuilder &MSF;
 
@@ -66,6 +80,12 @@ private:
   std::string ObjFileName;
   std::vector<std::string> SourceFiles;
   std::vector<codeview::CVSymbol> Symbols;
+  std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
+  std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> ChecksumInfo;
+
+  std::vector<std::unique_ptr<codeview::ModuleDebugFragmentRecordBuilder>>
+      C13Builders;
+
   ModuleInfoHeader Layout;
 };
 

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h Mon May  1 18:27:42 2017
@@ -59,6 +59,7 @@ public:
 
   Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
   Error addModuleSourceFile(StringRef Module, StringRef File);
+  Expected<uint32_t> getSourceFileNameIndex(StringRef FileName);
 
   Error finalizeMsfLayout();
 

Added: llvm/trunk/include/llvm/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.h?rev=301882&view=auto
==============================================================================
    (empty)

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h Mon May  1 18:27:42 2017
@@ -29,6 +29,7 @@ public:
   // If string S does not exist in the string table, insert it.
   // Returns the ID for S.
   uint32_t insert(StringRef S);
+  uint32_t getStringIndex(StringRef S);
 
   uint32_t finalize();
   Error commit(BinaryStreamWriter &Writer) const;

Modified: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp Mon May  1 18:27:42 2017
@@ -48,3 +48,50 @@ Error ModuleDebugFileChecksumFragmentRef
 
   return Error::success();
 }
+
+ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment()
+    : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {}
+
+void ModuleDebugFileChecksumFragment::addChecksum(uint32_t StringTableOffset,
+                                                  FileChecksumKind Kind,
+                                                  ArrayRef<uint8_t> Bytes) {
+  FileChecksumEntry Entry;
+  if (!Bytes.empty()) {
+    uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());
+    ::memcpy(Copy, Bytes.data(), Bytes.size());
+    Entry.Checksum = makeArrayRef(Copy, Bytes.size());
+  }
+  Entry.FileNameOffset = StringTableOffset;
+  Entry.Kind = Kind;
+  Checksums.push_back(Entry);
+
+  // This maps the offset of this string in the string table to the offset
+  // of this checksum entry in the checksum buffer.
+  OffsetMap[StringTableOffset] = SerializedSize;
+  SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size();
+}
+
+uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
+  return SerializedSize;
+}
+
+Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) {
+  for (const auto &FC : Checksums) {
+    FileChecksumEntryHeader Header;
+    Header.ChecksumKind = uint8_t(FC.Kind);
+    Header.ChecksumSize = FC.Checksum.size();
+    Header.FileNameOffset = FC.FileNameOffset;
+    if (auto EC = Writer.writeObject(Header))
+      return EC;
+    if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
+      return EC;
+  }
+  return Error::success();
+}
+
+uint32_t ModuleDebugFileChecksumFragment::mapChecksumOffset(
+    uint32_t StringTableOffset) const {
+  auto Iter = OffsetMap.find(StringTableOffset);
+  assert(Iter != OffsetMap.end());
+  return Iter->second;
+}

Modified: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp Mon May  1 18:27:42 2017
@@ -12,3 +12,5 @@
 using namespace llvm::codeview;
 
 ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {}
+
+ModuleDebugFragment::~ModuleDebugFragment() {}

Modified: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp Mon May  1 18:27:42 2017
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
 
 #include "llvm/Support/BinaryStreamReader.h"
 
@@ -30,6 +31,13 @@ Error ModuleDebugFragmentRecord::initial
 
   ModuleDebugFragmentKind Kind =
       static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind));
+  switch (Kind) {
+  case ModuleDebugFragmentKind::FileChecksums:
+  case ModuleDebugFragmentKind::Lines:
+    break;
+  default:
+    llvm_unreachable("Unexpected debug fragment kind!");
+  }
   if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
     return EC;
   Info.Kind = Kind;
@@ -37,7 +45,9 @@ Error ModuleDebugFragmentRecord::initial
 }
 
 uint32_t ModuleDebugFragmentRecord::getRecordLength() const {
-  return sizeof(ModuleDebugFragmentHeader) + Data.getLength();
+  uint32_t Result = sizeof(ModuleDebugFragmentHeader) + Data.getLength();
+  assert(Result % 4 == 0);
+  return Result;
 }
 
 ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; }
@@ -45,3 +55,29 @@ ModuleDebugFragmentKind ModuleDebugFragm
 BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const {
   return Data;
 }
+
+ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder(
+    ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag)
+    : Kind(Kind), Frag(Frag) {}
+
+uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() {
+  uint32_t Size = sizeof(ModuleDebugFragmentHeader) +
+                  alignTo(Frag.calculateSerializedLength(), 4);
+  return Size;
+}
+
+Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) {
+  ModuleDebugFragmentHeader Header;
+  Header.Kind = uint32_t(Kind);
+  Header.Length =
+      calculateSerializedLength() - sizeof(ModuleDebugFragmentHeader);
+
+  if (auto EC = Writer.writeObject(Header))
+    return EC;
+  if (auto EC = Frag.commit(Writer))
+    return EC;
+  if (auto EC = Writer.padToAlignment(4))
+    return EC;
+
+  return Error::success();
+}

Modified: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp Mon May  1 18:27:42 2017
@@ -64,3 +64,92 @@ Error ModuleDebugLineFragmentRef::initia
 bool ModuleDebugLineFragmentRef::hasColumnInfo() const {
   return !!(Header->Flags & LF_HaveColumns);
 }
+
+ModuleDebugLineFragment::ModuleDebugLineFragment()
+    : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {}
+
+void ModuleDebugLineFragment::createBlock(uint32_t ChecksumBufferOffset) {
+  Blocks.emplace_back(ChecksumBufferOffset);
+}
+
+void ModuleDebugLineFragment::addLineInfo(uint32_t Offset,
+                                          const LineInfo &Line) {
+  Block &B = Blocks.back();
+  LineNumberEntry LNE;
+  LNE.Flags = Line.getRawData();
+  LNE.Offset = Offset;
+  B.Lines.push_back(LNE);
+}
+
+void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset,
+                                                   const LineInfo &Line,
+                                                   uint32_t ColStart,
+                                                   uint32_t ColEnd) {
+  Block &B = Blocks.back();
+  assert(B.Lines.size() == B.Columns.size());
+
+  addLineInfo(Offset, Line);
+  ColumnNumberEntry CNE;
+  CNE.StartColumn = ColStart;
+  CNE.EndColumn = ColEnd;
+  B.Columns.push_back(CNE);
+}
+
+Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) {
+  LineFragmentHeader Header;
+  Header.CodeSize = CodeSize;
+  Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0;
+  Header.RelocOffset = RelocOffset;
+  Header.RelocSegment = RelocSegment;
+
+  if (auto EC = Writer.writeObject(Header))
+    return EC;
+
+  for (const auto &B : Blocks) {
+    LineBlockFragmentHeader BlockHeader;
+    assert(B.Lines.size() == B.Columns.size() || B.Columns.empty());
+
+    BlockHeader.NumLines = B.Lines.size();
+    BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader);
+    BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry);
+    if (hasColumnInfo())
+      BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry);
+    BlockHeader.NameIndex = B.ChecksumBufferOffset;
+    if (auto EC = Writer.writeObject(BlockHeader))
+      return EC;
+
+    if (auto EC = Writer.writeArray(makeArrayRef(B.Lines)))
+      return EC;
+
+    if (hasColumnInfo()) {
+      if (auto EC = Writer.writeArray(makeArrayRef(B.Columns)))
+        return EC;
+    }
+  }
+  return Error::success();
+}
+
+uint32_t ModuleDebugLineFragment::calculateSerializedLength() {
+  uint32_t Size = sizeof(LineFragmentHeader);
+  for (const auto &B : Blocks) {
+    Size += sizeof(LineBlockFragmentHeader);
+    Size += B.Lines.size() * sizeof(LineNumberEntry);
+    if (hasColumnInfo())
+      Size += B.Columns.size() * sizeof(ColumnNumberEntry);
+  }
+  return Size;
+}
+
+void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment,
+                                                   uint16_t Offset) {
+  RelocOffset = Offset;
+  RelocSegment = Segment;
+}
+
+void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; }
+
+void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; }
+
+bool ModuleDebugLineFragment::hasColumnInfo() const {
+  return Flags & LF_HaveColumns;
+}

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp Mon May  1 18:27:42 2017
@@ -110,6 +110,10 @@ const CVType &TypeDatabase::getTypeRecor
   return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
 }
 
+CVType &TypeDatabase::getTypeRecord(TypeIndex Index) {
+  return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
+}
+
 bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
   uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
   return I < CVUDTNames.size();

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp Mon May  1 18:27:42 2017
@@ -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 @@ template <> struct BinaryItemTraits<CVSy
 };
 }
 
-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 @@ DbiModuleDescriptorBuilder::DbiModuleDes
   Layout.Mod = ModIndex;
 }
 
+DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
+
 uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
   return Layout.ModDiStream;
 }
@@ -69,6 +73,15 @@ void DbiModuleDescriptorBuilder::addSour
   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 @@ void DbiModuleDescriptorBuilder::finaliz
   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 @@ void DbiModuleDescriptorBuilder::finaliz
 
 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 @@ Error DbiModuleDescriptorBuilder::commit
     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 @@ Error DbiModuleDescriptorBuilder::commit
   }
   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);
+}

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp Mon May  1 18:27:42 2017
@@ -101,6 +101,14 @@ Error DbiStreamBuilder::addModuleSourceF
   return Error::success();
 }
 
+Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
+  auto NameIter = SourceFileNames.find(File);
+  if (NameIter == SourceFileNames.end())
+    return make_error<RawError>(raw_error_code::no_entry,
+                                "The specified source file was not found");
+  return NameIter->getValue();
+}
+
 uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
   uint32_t Size = 0;
   for (const auto &M : ModiList)

Added: llvm/trunk/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/ModuleDebugStreamBuilder.cpp?rev=301882&view=auto
==============================================================================
    (empty)

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp Mon May  1 18:27:42 2017
@@ -29,6 +29,12 @@ uint32_t StringTableBuilder::insert(Stri
   return P.first->second;
 }
 
+uint32_t StringTableBuilder::getStringIndex(StringRef S) {
+  auto Iter = Strings.find(S);
+  assert(Iter != Strings.end());
+  return Iter->second;
+}
+
 static uint32_t computeBucketCount(uint32_t NumStrings) {
   // The /names stream is basically an on-disk open-addressing hash table.
   // Hash collisions are resolved by linear probing. We cannot make

Added: llvm/trunk/test/DebugInfo/PDB/Inputs/simple-line-info.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/simple-line-info.yaml?rev=301882&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/Inputs/simple-line-info.yaml (added)
+++ llvm/trunk/test/DebugInfo/PDB/Inputs/simple-line-info.yaml Mon May  1 18:27:42 2017
@@ -0,0 +1,38 @@
+---
+StringTable:
+  - 'junk_a'
+  - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
+  - 'junk_b'
+DbiStream:
+  Modules:
+    - Module:          'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
+      ObjFile:         'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
+      SourceFiles:
+        - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
+      LineInfo:
+        Checksums:
+          - FileName:        'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
+            Kind:            MD5
+            Checksum:        A0A5BD0D3ECD93FC29D19DE826FBF4BC
+        Lines:
+          - CodeSize:        10
+            Flags:           [  ]
+            RelocOffset:     16
+            RelocSegment:    1
+            Blocks:
+              - FileName:        'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
+                Lines:
+                  - Offset:          0
+                    LineStart:       5
+                    IsStatement:     true
+                    EndDelta:        0
+                  - Offset:          3
+                    LineStart:       6
+                    IsStatement:     true
+                    EndDelta:        0
+                  - Offset:          8
+                    LineStart:       7
+                    IsStatement:     true
+                    EndDelta:        0
+                Columns:
+...

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test Mon May  1 18:27:42 2017
@@ -495,11 +495,11 @@
 ; EMPTY-NEXT:           }
 ; EMPTY-NEXT:         }
 ; EMPTY-NEXT:         Lines {
-; EMPTY-NEXT:           LineFragment {
+; EMPTY-NEXT:           Block {
 ; EMPTY-NEXT:             RelocSegment: 1
 ; EMPTY-NEXT:             RelocOffset: 16
 ; EMPTY-NEXT:             CodeSize: 10
-; EMPTY-NEXT:             HasColumns: 0
+; EMPTY-NEXT:             HasColumns: No
 ; EMPTY-NEXT:             Lines {
 ; EMPTY-NEXT:               FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
 ; EMPTY-NEXT:               Line {

Added: llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test?rev=301882&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test (added)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test Mon May  1 18:27:42 2017
@@ -0,0 +1,52 @@
+; This testcase verifies that we can produce a PDB with line
+; information.  It does this by describing some line information
+; manually in YAML, creating a PDB out of it, then dumping then
+; line information from the resulting PDB.
+
+; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/simple-line-info.yaml
+; RUN: llvm-pdbdump raw -line-info %t.pdb | FileCheck -check-prefix=LINES %s
+
+LINES:       Modules [
+LINES-NEXT:    {
+LINES-NEXT:      Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
+LINES:           LineInfo [
+LINES-NEXT:        FileChecksums {
+LINES-NEXT:          Checksum {
+LINES-NEXT:            FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+LINES-NEXT:            Kind: MD5 (0x1)
+LINES-NEXT:            Checksum (
+LINES-NEXT:              0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC  |....>...)...&...|
+LINES-NEXT:            )
+LINES-NEXT:          }
+LINES-NEXT:        }
+LINES-NEXT:        Lines {
+LINES-NEXT:          Block {
+LINES-NEXT:            RelocSegment: 1
+LINES-NEXT:            RelocOffset: 16
+LINES-NEXT:            CodeSize: 10
+LINES-NEXT:            HasColumns: No
+LINES-NEXT:            Lines {
+LINES-NEXT:              FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+LINES-NEXT:              Line {
+LINES-NEXT:                Offset: 0
+LINES-NEXT:                LineNumberStart: 5
+LINES-NEXT:                EndDelta: 0
+LINES-NEXT:                IsStatement: Yes
+LINES-NEXT:              }
+LINES-NEXT:              Line {
+LINES-NEXT:                Offset: 3
+LINES-NEXT:                LineNumberStart: 6
+LINES-NEXT:                EndDelta: 0
+LINES-NEXT:                IsStatement: Yes
+LINES-NEXT:              }
+LINES-NEXT:              Line {
+LINES-NEXT:                Offset: 8
+LINES-NEXT:                LineNumberStart: 7
+LINES-NEXT:                EndDelta: 0
+LINES-NEXT:                IsStatement: Yes
+LINES-NEXT:              }
+LINES-NEXT:            }
+LINES-NEXT:          }
+LINES-NEXT:        }
+LINES-NEXT:      ]
+LINES-NEXT:    }

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Mon May  1 18:27:42 2017
@@ -89,11 +89,11 @@ public:
     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 @@ Error LLVMOutputStyle::dumpTpiStream(uin
 
   bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
   if (IsSilentDatabaseBuild) {
+    outs().flush();
     errs() << "Building Type Information For " << Label << "\n";
   }
 

Modified: llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp Mon May  1 18:27:42 2017
@@ -286,8 +286,7 @@ Error YAMLOutputStyle::dumpDbiStream() {
         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())

Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=301882&r1=301881&r2=301882&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Mon May  1 18:27:42 2017
@@ -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 @@ static void yamlToPdb(StringRef Path) {
       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();




More information about the llvm-commits mailing list