<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 15, 2017 at 2:23 PM, Eric Beckmann <span dir="ltr"><<a href="mailto:ecbeckmann@google.com" target="_blank">ecbeckmann@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I'm sorry are you referring to a particular part of the patch?  Do you mean we shouldn't give the ChecksumKind enum explicit values but rather save those for the assembler to give?</div></blockquote><div><br></div><div>I think its fine for ChecksumKind to have explicit values. I just don't think its great that they are dependent on the encoding used by CodeView. The assembler should translate the LLVM-internal CSK_MD5 to the CodeView specific CHKSUM_TYPE_MD5.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 15, 2017 at 2:11 PM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="gmail-m_-3027850383123096161h5">On Fri, Sep 15, 2017 at 11:20 AM, Eric Beckmann via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: ecbeckmann<br>
Date: Fri Sep 15 11:20:28 2017<br>
New Revision: 313374<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=313374&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=313374&view=rev</a><br>
Log:<br>
Fix Bug 30978 by emitting cv file checksums.<br>
<br>
Summary:<br>
The checksums had already been placed in the IR, this patch allows<br>
MCCodeView to actually write it out to an MCStreamer.<br>
<br>
Subscribers: llvm-commits, hiraditya<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D37157" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3715<wbr>7</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/Deb<wbr>ugInfoMetadata.h<br>
    llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h<br>
    llvm/trunk/include/llvm/MC/MCO<wbr>bjectStreamer.h<br>
    llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h<br>
    llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp<br>
    llvm/trunk/lib/IR/DebugInfoMet<wbr>adata.cpp<br>
    llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp<br>
    llvm/trunk/lib/MC/MCCodeView.c<wbr>pp<br>
    llvm/trunk/lib/MC/MCObjectStre<wbr>amer.cpp<br>
    llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp<br>
    llvm/trunk/lib/MC/MCStreamer.c<wbr>pp<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/inlining.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/multifile.ll<br>
    llvm/trunk/test/DebugInfo/COFF<wbr>/simple.ll<br>
    llvm/trunk/test/MC/AArch64/cof<wbr>f-debug.ll<br>
    llvm/trunk/unittests/IR/Metada<wbr>taTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Deb<wbr>ugInfoMetadata.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>IR/DebugInfoMetadata.h?rev=313<wbr>374&r1=313373&r2=313374&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/IR/Deb<wbr>ugInfoMetadata.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Deb<wbr>ugInfoMetadata.h Fri Sep 15 11:20:28 2017<br>
@@ -473,10 +473,12 @@ class DIFile : public DIScope {<br>
   friend class MDNode;<br>
<br>
 public:<br>
+  // These values must be explictly set, as they end up in the final object<br>
+  // file.<br></blockquote><div><br></div></div></div><div>This seems weird. Shouldn't we separate this from what we actually encode and translate it to the codeview specific CHKSUM_TYPE_MD5/CHKSUM_TYPE_SH<wbr>A1?</div><div><br></div><div>I know that the conversion would be trivial but this seems like a bit of a layering violation, especially considering that we encode the ChecksumKind in the bitcode itself...</div><div><div class="gmail-m_-3027850383123096161h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
   enum ChecksumKind {<br>
-    CSK_None,<br>
-    CSK_MD5,<br>
-    CSK_SHA1,<br>
+    CSK_None = 0,<br>
+    CSK_MD5 = 1,<br>
+    CSK_SHA1 = 2,<br>
     CSK_Last = CSK_SHA1 // Should be last enumeration.<br>
   };<br>
<br>
@@ -510,7 +512,7 @@ public:<br>
                              ChecksumKind CSK = CSK_None,<br>
                              StringRef CS = StringRef()),<br>
                     (Filename, Directory, CSK, CS))<br>
-  DEFINE_MDNODE_GET(DIFile, (MDString *Filename, MDString *Directory,<br>
+  DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory,<br>
                              ChecksumKind CSK = CSK_None,<br>
                              MDString *CS = nullptr),<br>
                     (Filename, Directory, CSK, CS))<br>
<br>
Modified: llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCCodeView.h?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>MC/MCCodeView.h?rev=313374&r1=<wbr>313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h (original)<br>
+++ llvm/trunk/include/llvm/MC/MCC<wbr>odeView.h Fri Sep 15 11:20:28 2017<br>
@@ -161,8 +161,8 @@ public:<br>
   ~CodeViewContext();<br>
<br>
   bool isValidFileNumber(unsigned FileNumber) const;<br>
-  bool addFile(unsigned FileNumber, StringRef Filename);<br>
-  ArrayRef<StringRef> getFilenames() { return Filenames; }<br>
+  bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,<br>
+               StringRef Checksum, uint8_t ChecksumKind);<br>
<br>
   /// Records the function id of a normal function. Returns false if the<br>
   /// function id has already been used, and true otherwise.<br>
@@ -273,6 +273,9 @@ public:<br>
   /// Emits the file checksum substream.<br>
   void emitFileChecksums(MCObjectStre<wbr>amer &OS);<br>
<br>
+  /// Emits the offset into the checksum table of the given file number.<br>
+  void emitFileChecksumOffset(MCObjec<wbr>tStreamer &OS, unsigned FileNo);<br>
+<br>
 private:<br>
   /// The current CodeView line information from the last .cv_loc directive.<br>
   MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);<br>
@@ -287,14 +290,30 @@ private:<br>
<br>
   MCDataFragment *getStringTableFragment();<br>
<br>
-  /// Add something to the string table.<br>
-  StringRef addToStringTable(StringRef S);<br>
+  /// Add something to the string table.  Returns the final string as well as<br>
+  /// offset into the string table.<br>
+  std::pair<StringRef, unsigned> addToStringTable(StringRef S);<br>
<br>
   /// Get a string table offset.<br>
   unsigned getStringTableOffset(StringRef S);<br>
<br>
-  /// An array of absolute paths. Eventually this may include the file checksum.<br>
-  SmallVector<StringRef, 4> Filenames;<br>
+  struct FileInfo {<br>
+    unsigned StringTableOffset;<br>
+<br>
+    // Checksum offset stored as a symbol because it might be requested<br>
+    // before it has been calculated, so a fixup may be needed.<br>
+    MCSymbol *ChecksumTableOffset;<br>
+<br>
+    // Indicates if this FileInfo corresponds to an actual file, or hasn't been<br>
+    // set yet.<br>
+    bool Assigned = false;<br>
+<br>
+    std::string Checksum;<br>
+    uint8_t ChecksumKind;<br>
+  };<br>
+<br>
+  /// Array storing added file information.<br>
+  SmallVector<FileInfo, 4> Files;<br>
<br>
   /// The offset of the first and last .cv_loc directive for a given function<br>
   /// id.<br>
@@ -305,6 +324,10 @@ private:<br>
<br>
   /// All known functions and inlined call sites, indexed by function id.<br>
   std::vector<MCCVFunctionInfo> Functions;<br>
+<br>
+  /// Indicate whether we have already laid out the checksum table addresses or<br>
+  /// not.<br>
+  bool ChecksumOffsetsAssigned = false;<br>
 };<br>
<br>
 } // end namespace llvm<br>
<br>
Modified: llvm/trunk/include/llvm/MC/MCO<wbr>bjectStreamer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>MC/MCObjectStreamer.h?rev=3133<wbr>74&r1=313373&r2=313374&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/MC/MCO<wbr>bjectStreamer.h (original)<br>
+++ llvm/trunk/include/llvm/MC/MCO<wbr>bjectStreamer.h Fri Sep 15 11:20:28 2017<br>
@@ -140,6 +140,7 @@ public:<br>
       StringRef FixedSizePortion) override;<br>
   void EmitCVStringTableDirective() override;<br>
   void EmitCVFileChecksumsDirective() override;<br>
+  void EmitCVFileChecksumOffsetDirect<wbr>ive(unsigned FileNo) override;<br>
   void EmitDTPRel32Value(const MCExpr *Value) override;<br>
   void EmitDTPRel64Value(const MCExpr *Value) override;<br>
   void EmitTPRel32Value(const MCExpr *Value) override;<br>
<br>
Modified: llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>MC/MCStreamer.h?rev=313374&r1=<wbr>313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h (original)<br>
+++ llvm/trunk/include/llvm/MC/MCS<wbr>treamer.h Fri Sep 15 11:20:28 2017<br>
@@ -729,10 +729,11 @@ public:<br>
                                      unsigned Isa, unsigned Discriminator,<br>
                                      StringRef FileName);<br>
<br>
-  /// \brief Associate a filename with a specified logical file number.  This<br>
-  /// implements the '.cv_file 4 "foo.c"' assembler directive. Returns true on<br>
-  /// success.<br>
-  virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename);<br>
+  /// Associate a filename with a specified logical file number, and also<br>
+  /// specify that file's checksum information.  This implements the '.cv_file 4<br>
+  /// "foo.c"' assembler directive. Returns true on success.<br>
+  virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,<br>
+                                   StringRef Checksum, unsigned ChecksumKind);<br>
<br>
   /// \brief Introduces a function id for use with .cv_loc.<br>
   virtual bool EmitCVFuncIdDirective(unsigned FunctionId);<br>
@@ -774,6 +775,10 @@ public:<br>
   /// \brief This implements the CodeView '.cv_filechecksums' assembler directive.<br>
   virtual void EmitCVFileChecksumsDirective() {}<br>
<br>
+  /// This implements the CodeView '.cv_filechecksumoffset' assembler<br>
+  /// directive.<br>
+  virtual void EmitCVFileChecksumOffsetDirect<wbr>ive(unsigned FileNo) {}<br>
+<br>
   /// Emit the absolute difference between two symbols.<br>
   ///<br>
   /// \pre Offset of \c Hi is greater than the offset \c Lo.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/CodeGen/A<wbr>smPrinter/CodeViewDebug.cpp?re<wbr>v=313374&r1=313373&r2=313374&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrin<wbr>ter/CodeViewDebug.cpp Fri Sep 15 11:20:28 2017<br>
@@ -159,7 +159,10 @@ unsigned CodeViewDebug::maybeRecordFile<wbr>(<br>
   if (Insertion.second) {<br>
     // We have to compute the full filepath and emit a .cv_file directive.<br>
     StringRef FullPath = getFullFilepath(F);<br>
-    bool Success = OS.EmitCVFileDirective(NextId, FullPath);<br>
+    StringRef Checksum = F->getChecksum();<br>
+    DIFile::ChecksumKind ChecksumKind = F->getChecksumKind();<br>
+    bool Success = OS.EmitCVFileDirective(NextId, FullPath, Checksum,<br>
+                                          static_cast<unsigned>(Checksum<wbr>Kind));<br>
     (void)Success;<br>
     assert(Success && ".cv_file directive failed");<br>
   }<br>
@@ -681,8 +684,10 @@ void CodeViewDebug::emitInlineeLine<wbr>sSubs<br>
   OS.AddComment("Inlinee lines subsection");<br>
   MCSymbol *InlineEnd = beginCVSubsection(DebugSubsect<wbr>ionKind::InlineeLines);<br>
<br>
-  // We don't provide any extra file info.<br>
-  // FIXME: Find out if debuggers use this info.<br>
+  // We emit the checksum info for files.  This is used by debuggers to<br>
+  // determine if a pdb matches the source before loading it.  Visual Studio,<br>
+  // for instance, will display a warning that the breakpoints are not valid if<br>
+  // the pdb does not match the source.<br>
   OS.AddComment("Inlinee lines signature");<br>
   OS.EmitIntValue(unsigned(Inli<wbr>neeLinesSignature::Normal), 4);<br>
<br>
@@ -695,13 +700,10 @@ void CodeViewDebug::emitInlineeLine<wbr>sSubs<br>
     OS.AddComment("Inlined function " + SP->getName() + " starts at " +<br>
                   SP->getFilename() + Twine(':') + Twine(SP->getLine()));<br>
     OS.AddBlankLine();<br>
-    // The filechecksum table uses 8 byte entries for now, and file ids start at<br>
-    // 1.<br>
-    unsigned FileOffset = (FileId - 1) * 8;<br>
     OS.AddComment("Type index of inlined function");<br>
     OS.EmitIntValue(InlineeIdx.ge<wbr>tIndex(), 4);<br>
     OS.AddComment("Offset into filechecksum table");<br>
-    OS.EmitIntValue(FileOffset, 4);<br>
+    OS.EmitCVFileChecksumOffsetDir<wbr>ective(FileId);<br>
     OS.AddComment("Starting line number");<br>
     OS.EmitIntValue(SP->getLine()<wbr>, 4);<br>
   }<br>
<br>
Modified: llvm/trunk/lib/IR/DebugInfoMet<wbr>adata.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/DebugI<wbr>nfoMetadata.cpp?rev=313374&r1=<wbr>313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/DebugInfoMet<wbr>adata.cpp (original)<br>
+++ llvm/trunk/lib/IR/DebugInfoMet<wbr>adata.cpp Fri Sep 15 11:20:28 2017<br>
@@ -354,6 +354,8 @@ DISubroutineType *DISubroutineType::getI<br>
   DEFINE_GETIMPL_STORE(DISubrou<wbr>tineType, (Flags, CC), Ops);<br>
 }<br>
<br>
+// FIXME: Implement this string-enum correspondence with a .def file and macros,<br>
+// so that the association is explicit rather than implied.<br>
 static const char *ChecksumKindName[DIFile::CSK_<wbr>Last + 1] = {<br>
   "CSK_None",<br>
   "CSK_MD5",<br>
<br>
Modified: llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCAsmS<wbr>treamer.cpp?rev=313374&r1=3133<wbr>73&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCAsmStreame<wbr>r.cpp Fri Sep 15 11:20:28 2017<br>
@@ -225,7 +225,8 @@ public:<br>
                              StringRef FileName) override;<br>
   MCSymbol *getDwarfLineTableSymbol(unsig<wbr>ned CUID) override;<br>
<br>
-  bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;<br>
+  bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,<br>
+                           StringRef Checksum, unsigned ChecksumKind) override;<br>
   bool EmitCVFuncIdDirective(unsigned FuncId) override;<br>
   bool EmitCVInlineSiteIdDirective(un<wbr>signed FunctionId, unsigned IAFunc,<br>
                                    unsigned IAFile, unsigned IALine,<br>
@@ -245,6 +246,7 @@ public:<br>
       StringRef FixedSizePortion) override;<br>
   void EmitCVStringTableDirective() override;<br>
   void EmitCVFileChecksumsDirective() override;<br>
+  void EmitCVFileChecksumOffsetDirect<wbr>ive(unsigned FileNo) override;<br>
<br>
   void EmitIdent(StringRef IdentString) override;<br>
   void EmitCFISections(bool EH, bool Debug) override;<br>
@@ -1120,13 +1122,25 @@ MCSymbol *MCAsmStreamer::getDwarfLineTa<wbr>b<br>
   return MCStreamer::getDwarfLineTableS<wbr>ymbol(0);<br>
 }<br>
<br>
-bool MCAsmStreamer::EmitCVFileDirec<wbr>tive(unsigned FileNo, StringRef Filename) {<br>
-  if (!getContext().getCVContext().<wbr>addFile(FileNo, Filename))<br>
+bool MCAsmStreamer::EmitCVFileDirec<wbr>tive(unsigned FileNo, StringRef Filename,<br>
+                                        StringRef Checksum,<br>
+                                        unsigned ChecksumKind) {<br>
+  if (!getContext().getCVContext().<wbr>addFile(*this, FileNo, Filename, Checksum,<br>
+                                           ChecksumKind))<br>
     return false;<br>
<br>
   OS << "\t.cv_file\t" << FileNo << ' ';<br>
-<br>
   PrintQuotedString(Filename, OS);<br>
+<br>
+  if (!ChecksumKind) {<br>
+    EmitEOL();<br>
+    return true;<br>
+  }<br>
+<br>
+  OS << ' ';<br>
+  PrintQuotedString(Checksum, OS);<br>
+  OS << ' ' << ChecksumKind;<br>
+<br>
   EmitEOL();<br>
   return true;<br>
 }<br>
@@ -1228,6 +1242,11 @@ void MCAsmStreamer::EmitCVFileCheck<wbr>sumsD<br>
   EmitEOL();<br>
 }<br>
<br>
+void MCAsmStreamer::EmitCVFileCheck<wbr>sumOffsetDirective(unsigned FileNo) {<br>
+  OS << "\t.cv_filechecksumoffset\t" << FileNo;<br>
+  EmitEOL();<br>
+}<br>
+<br>
 void MCAsmStreamer::EmitIdent(Strin<wbr>gRef IdentString) {<br>
   assert(MAI->hasIdentDirective<wbr>() && ".ident directive not supported");<br>
   OS << "\t.ident\t";<br>
<br>
Modified: llvm/trunk/lib/MC/MCCodeView.c<wbr>pp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCCodeView.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCCode<wbr>View.cpp?rev=313374&r1=313373&<wbr>r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCCodeView.c<wbr>pp (original)<br>
+++ llvm/trunk/lib/MC/MCCodeView.c<wbr>pp Fri Sep 15 11:20:28 2017<br>
@@ -39,29 +39,39 @@ CodeViewContext::~CodeViewCont<wbr>ext() {<br>
 /// for it.<br>
 bool CodeViewContext::isValidFileNu<wbr>mber(unsigned FileNumber) const {<br>
   unsigned Idx = FileNumber - 1;<br>
-  if (Idx < Filenames.size())<br>
-    return !Filenames[Idx].empty();<br>
+  if (Idx < Files.size())<br>
+    return Files[Idx].Assigned;<br>
   return false;<br>
 }<br>
<br>
-bool CodeViewContext::addFile(unsig<wbr>ned FileNumber, StringRef Filename) {<br>
+bool CodeViewContext::addFile(MCStr<wbr>eamer &OS, unsigned FileNumber,<br>
+                              StringRef Filename, StringRef Checksum,<br>
+                              uint8_t ChecksumKind) {<br>
   assert(FileNumber > 0);<br>
-  Filename = addToStringTable(Filename);<br>
+  auto FilenameOffset = addToStringTable(Filename);<br>
+  Filename = FilenameOffset.first;<br>
   unsigned Idx = FileNumber - 1;<br>
-  if (Idx >= Filenames.size())<br>
-    Filenames.resize(Idx + 1);<br>
+  if (Idx >= Files.size())<br>
+    Files.resize(Idx + 1);<br>
<br>
   if (Filename.empty())<br>
     Filename = "<stdin>";<br>
<br>
-  if (!Filenames[Idx].empty())<br>
+  if (Files[Idx].Assigned)<br>
     return false;<br>
<br>
-  // FIXME: We should store the string table offset of the filename, rather than<br>
-  // the filename itself for efficiency.<br>
-  Filename = addToStringTable(Filename);<br>
+  FilenameOffset = addToStringTable(Filename);<br>
+  Filename = FilenameOffset.first;<br>
+  unsigned Offset = FilenameOffset.second;<br>
+<br>
+  auto ChecksumOffsetSymbol =<br>
+      OS.getContext().createTempSymb<wbr>ol("checksum_offset", false);<br>
+  Files[Idx].StringTableOffset = Offset;<br>
+  Files[Idx].ChecksumTableOffset = ChecksumOffsetSymbol;<br>
+  Files[Idx].Assigned = true;<br>
+  Files[Idx].Checksum = Checksum.str();<br>
+  Files[Idx].ChecksumKind = ChecksumKind;<br>
<br>
-  Filenames[Idx] = Filename;<br>
   return true;<br>
 }<br>
<br>
@@ -118,17 +128,18 @@ MCDataFragment *CodeViewContext::getStri<br>
   return StrTabFragment;<br>
 }<br>
<br>
-StringRef CodeViewContext::addToStringTa<wbr>ble(StringRef S) {<br>
+std::pair<StringRef, unsigned> CodeViewContext::addToStringTa<wbr>ble(StringRef S) {<br>
   SmallVectorImpl<char> &Contents = getStringTableFragment()->getC<wbr>ontents();<br>
   auto Insertion =<br>
       StringTable.insert(std::make_<wbr>pair(S, unsigned(Contents.size())));<br>
   // Return the string from the table, since it is stable.<br>
-  S = Insertion.first->first();<br>
+  std::pair<StringRef, unsigned> Ret =<br>
+      std::make_pair(Insertion.first<wbr>->first(), Insertion.first->second);<br>
   if (Insertion.second) {<br>
     // The string map key is always null terminated.<br>
-    Contents.append(S.begin(), S.end() + 1);<br>
+    Contents.append(Ret.first.begi<wbr>n(), Ret.first.end() + 1);<br>
   }<br>
-  return S;<br>
+  return Ret;<br>
 }<br>
<br>
 unsigned CodeViewContext::getStringTabl<wbr>eOffset(StringRef S) {<br>
@@ -165,7 +176,7 @@ void CodeViewContext::emitStringTab<wbr>le(MC<br>
 void CodeViewContext::emitFileCheck<wbr>sums(MCObjectStreamer &OS) {<br>
   // Do nothing if there are no file checksums. Microsoft's linker rejects empty<br>
   // CodeView substreams.<br>
-  if (Filenames.empty())<br>
+  if (Files.empty())<br>
     return;<br>
<br>
   MCContext &Ctx = OS.getContext();<br>
@@ -176,17 +187,63 @@ void CodeViewContext::emitFileCheck<wbr>sums(<br>
   OS.emitAbsoluteSymbolDiff(Fil<wbr>eEnd, FileBegin, 4);<br>
   OS.EmitLabel(FileBegin);<br>
<br>
+  unsigned CurrentOffset = 0;<br>
+<br>
   // Emit an array of FileChecksum entries. We index into this table using the<br>
-  // user-provided file number. Each entry is currently 8 bytes, as we don't<br>
-  // emit checksums.<br>
-  for (StringRef Filename : Filenames) {<br>
-    OS.EmitIntValue(getStringTable<wbr>Offset(Filename), 4);<br>
-    // Zero the next two fields and align back to 4 bytes. This indicates that<br>
-    // no checksum is present.<br>
-    OS.EmitIntValue(0, 4);<br>
+  // user-provided file number.  Each entry may be a variable number of bytes<br>
+  // determined by the checksum kind and size.<br>
+  for (auto File : Files) {<br>
+    OS.EmitAssignment(File.Checksu<wbr>mTableOffset,<br>
+                      MCConstantExpr::create(Current<wbr>Offset, Ctx));<br>
+    CurrentOffset += 4; // String table offset.<br>
+    if (!File.ChecksumKind) {<br>
+      CurrentOffset +=<br>
+          4; // One byte each for checksum size and kind, then align to 4 bytes.<br>
+    } else {<br>
+      CurrentOffset += 2; // One byte each for checksum size and kind.<br>
+      CurrentOffset += File.Checksum.size();<br>
+      CurrentOffset = alignTo(CurrentOffset, 4);<br>
+    }<br>
+<br>
+    OS.EmitIntValue(File.StringTab<wbr>leOffset, 4);<br>
+<br>
+    if (!File.ChecksumKind) {<br>
+      // There is no checksum.  Therefore zero the next two fields and align<br>
+      // back to 4 bytes.<br>
+      OS.EmitIntValue(0, 4);<br>
+      continue;<br>
+    }<br>
+    OS.EmitIntValue(static_cast<ui<wbr>nt8_t>(File.Checksum.size()), 1);<br>
+    OS.EmitIntValue(File.ChecksumK<wbr>ind, 1);<br>
+    OS.EmitBytes(File.Checksum);<br>
+    OS.EmitValueToAlignment(4);<br>
   }<br>
<br>
   OS.EmitLabel(FileEnd);<br>
+<br>
+  ChecksumOffsetsAssigned = true;<br>
+}<br>
+<br>
+// Output checksum table offset of the given file number.  It is possible that<br>
+// not all files have been registered yet, and so the offset cannot be<br>
+// calculated.  In this case a symbol representing the offset is emitted, and<br>
+// the value of this symbol will be fixed up at a later time.<br>
+void CodeViewContext::emitFileCheck<wbr>sumOffset(MCObjectStreamer &OS,<br>
+                                             unsigned FileNo) {<br>
+  unsigned Idx = FileNo - 1;<br>
+<br>
+  if (Idx >= Files.size())<br>
+    Files.resize(Idx + 1);<br>
+<br>
+  if (ChecksumOffsetsAssigned) {<br>
+    OS.EmitSymbolValue(Files[Idx].<wbr>ChecksumTableOffset, 4);<br>
+    return;<br>
+  }<br>
+<br>
+  const MCSymbolRefExpr *SRE =<br>
+      MCSymbolRefExpr::create(Files[<wbr>Idx].ChecksumTableOffset, OS.getContext());<br>
+<br>
+  OS.EmitValueImpl(SRE, 4);<br>
 }<br>
<br>
 void CodeViewContext::emitLineTable<wbr>ForFunction(MCObjectStreamer &OS,<br>
@@ -219,9 +276,12 @@ void CodeViewContext::emitLineTable<wbr>ForFu<br>
           return Loc.getFileNum() != CurFileNum;<br>
         });<br>
     unsigned EntryCount = FileSegEnd - I;<br>
-    OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +<br>
-                  "' begins");<br>
-    OS.EmitIntValue(8 * (CurFileNum - 1), 4);<br>
+    OS.AddComment(<br>
+        "Segment for file '" +<br>
+        Twine(getStringTableFragment()<br>
+                  ->getContents()[Files[CurFileN<wbr>um - 1].StringTableOffset]) +<br>
+        "' begins");<br>
+    OS.EmitCVFileChecksumOffsetDir<wbr>ective(CurFileNum);<br>
     OS.EmitIntValue(EntryCount, 4);<br>
     uint32_t SegmentSize = 12;<br>
     SegmentSize += 8 * EntryCount;<br>
@@ -401,9 +461,10 @@ void CodeViewContext::encodeInlineL<wbr>ineTa<br>
     HaveOpenRange = true;<br>
<br>
     if (CurSourceLoc.File != LastSourceLoc.File) {<br>
-      // File ids are 1 based, and each file checksum table entry is 8 bytes<br>
-      // long. See emitFileChecksums above.<br>
-      unsigned FileOffset = 8 * (CurSourceLoc.File - 1);<br>
+      unsigned FileOffset = static_cast<const MCConstantExpr *>(<br>
+                                Files[CurSourceLoc.File - 1]<br>
+                                    .ChecksumTableOffset->getVaria<wbr>bleValue())<br>
+                                ->getValue();<br>
       compressAnnotation(BinaryAnno<wbr>tationsOpCode::ChangeFile, Buffer);<br>
       compressAnnotation(FileOffset<wbr>, Buffer);<br>
     }<br>
<br>
Modified: llvm/trunk/lib/MC/MCObjectStre<wbr>amer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCObje<wbr>ctStreamer.cpp?rev=313374&r1=3<wbr>13373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCObjectStre<wbr>amer.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCObjectStre<wbr>amer.cpp Fri Sep 15 11:20:28 2017<br>
@@ -426,6 +426,9 @@ void MCObjectStreamer::EmitCVFileCh<wbr>ecksu<br>
   getContext().getCVContext().e<wbr>mitFileChecksums(*this);<br>
 }<br>
<br>
+void MCObjectStreamer::EmitCVFileCh<wbr>ecksumOffsetDirective(unsigned FileNo) {<br>
+  getContext().getCVContext().em<wbr>itFileChecksumOffset(*this, FileNo);<br>
+}<br>
<br>
 void MCObjectStreamer::EmitBytes(St<wbr>ringRef Data) {<br>
   MCCVLineEntry::Make(this);<br>
<br>
Modified: llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCPars<wbr>er/AsmParser.cpp?rev=313374&r1<wbr>=313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp (original)<br>
+++ llvm/trunk/lib/MC/MCParser/Asm<wbr>Parser.cpp Fri Sep 15 11:20:28 2017<br>
@@ -501,6 +501,7 @@ private:<br>
     DK_CV_DEF_RANGE,<br>
     DK_CV_STRINGTABLE,<br>
     DK_CV_FILECHECKSUMS,<br>
+    DK_CV_FILECHECKSUM_OFFSET,<br>
     DK_CFI_SECTIONS,<br>
     DK_CFI_STARTPROC,<br>
     DK_CFI_ENDPROC,<br>
@@ -576,6 +577,7 @@ private:<br>
   bool parseDirectiveCVDefRange();<br>
   bool parseDirectiveCVStringTable();<br>
   bool parseDirectiveCVFileChecksums(<wbr>);<br>
+  bool parseDirectiveCVFileChecksumOf<wbr>fset();<br>
<br>
   // .cfi directives<br>
   bool parseDirectiveCFIRegister(SMLo<wbr>c DirectiveLoc);<br>
@@ -2030,6 +2032,8 @@ bool AsmParser::parseStatement(Pars<wbr>eStat<br>
       return parseDirectiveCVStringTable();<br>
     case DK_CV_FILECHECKSUMS:<br>
       return parseDirectiveCVFileChecksums(<wbr>);<br>
+    case DK_CV_FILECHECKSUM_OFFSET:<br>
+      return parseDirectiveCVFileChecksumOf<wbr>fset();<br>
     case DK_CFI_SECTIONS:<br>
       return parseDirectiveCFISections();<br>
     case DK_CFI_STARTPROC:<br>
@@ -3457,25 +3461,34 @@ bool AsmParser::parseDirectiveStabs<wbr>() {<br>
 }<br>
<br>
 /// parseDirectiveCVFile<br>
-/// ::= .cv_file number filename<br>
+/// ::= .cv_file number filename [checksum] [checksumkind]<br>
 bool AsmParser::parseDirectiveCVFil<wbr>e() {<br>
   SMLoc FileNumberLoc = getTok().getLoc();<br>
   int64_t FileNumber;<br>
   std::string Filename;<br>
+  std::string Checksum;<br>
+  int64_t ChecksumKind = 0;<br>
<br>
   if (parseIntToken(FileNumber,<br>
                     "expected file number in '.cv_file' directive") ||<br>
       check(FileNumber < 1, FileNumberLoc, "file number less than one") ||<br>
       check(getTok().isNot(AsmToken<wbr>::String),<br>
             "unexpected token in '.cv_file' directive") ||<br>
-      // Usually directory and filename are together, otherwise just<br>
-      // directory. Allow the strings to have escaped octal character sequence.<br>
-      parseEscapedString(Filename) ||<br>
-      parseToken(AsmToken::EndOfStat<wbr>ement,<br>
-                 "unexpected token in '.cv_file' directive"))<br>
+      parseEscapedString(Filename))<br>
     return true;<br>
+  if (!parseOptionalToken(AsmToken:<wbr>:EndOfStatement)) {<br>
+    if (check(getTok().isNot(AsmToken<wbr>::String),<br>
+              "unexpected token in '.cv_file' directive") ||<br>
+        parseEscapedString(Checksum) ||<br>
+        parseIntToken(ChecksumKind,<br>
+                      "expected checksum kind in '.cv_file' directive") ||<br>
+        parseToken(AsmToken::EndOfStat<wbr>ement,<br>
+                   "unexpected token in '.cv_file' directive"))<br>
+      return true;<br>
+  }<br>
<br>
-  if (!getStreamer().EmitCVFileDire<wbr>ctive(FileNumber, Filename))<br>
+  if (!getStreamer().EmitCVFileDire<wbr>ctive(FileNumber, Filename, Checksum,<br>
+                                         static_cast<uint8_t>(Checksum<wbr>Kind)))<br>
     return Error(FileNumberLoc, "file number already allocated");<br>
<br>
   return false;<br>
@@ -3754,6 +3767,18 @@ bool AsmParser::parseDirectiveCVFil<wbr>eChec<br>
   return false;<br>
 }<br>
<br>
+/// parseDirectiveCVFileChecksumOf<wbr>fset<br>
+/// ::= .cv_filechecksumoffset fileno<br>
+bool AsmParser::parseDirectiveCVFil<wbr>eChecksumOffset() {<br>
+  int64_t FileNo;<br>
+  if (parseIntToken(FileNo, "expected identifier in directive"))<br>
+    return true;<br>
+  if (parseToken(AsmToken::EndOfSta<wbr>tement, "Expected End of Statement"))<br>
+    return true;<br>
+  getStreamer().EmitCVFileChecks<wbr>umOffsetDirective(FileNo);<br>
+  return false;<br>
+}<br>
+<br>
 /// parseDirectiveCFISections<br>
 /// ::= .cfi_sections section [, section]<br>
 bool AsmParser::parseDirectiveCFISe<wbr>ctions() {<br>
@@ -5136,6 +5161,7 @@ void AsmParser::initializeDirective<wbr>KindM<br>
   DirectiveKindMap[".cv_def_ran<wbr>ge"] = DK_CV_DEF_RANGE;<br>
   DirectiveKindMap[".cv_stringt<wbr>able"] = DK_CV_STRINGTABLE;<br>
   DirectiveKindMap[".cv_fileche<wbr>cksums"] = DK_CV_FILECHECKSUMS;<br>
+  DirectiveKindMap[".cv_filechec<wbr>ksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;<br>
   DirectiveKindMap[".sleb128"] = DK_SLEB128;<br>
   DirectiveKindMap[".uleb128"] = DK_ULEB128;<br>
   DirectiveKindMap[".cfi_sectio<wbr>ns"] = DK_CFI_SECTIONS;<br>
<br>
Modified: llvm/trunk/lib/MC/MCStreamer.c<wbr>pp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/MC/MCStre<wbr>amer.cpp?rev=313374&r1=313373&<wbr>r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/MC/MCStreamer.c<wbr>pp (original)<br>
+++ llvm/trunk/lib/MC/MCStreamer.c<wbr>pp Fri Sep 15 11:20:28 2017<br>
@@ -224,8 +224,11 @@ void MCStreamer::EnsureValidDwarfFr<wbr>ame()<br>
     report_fatal_error("No open frame");<br>
 }<br>
<br>
-bool MCStreamer::EmitCVFileDirectiv<wbr>e(unsigned FileNo, StringRef Filename) {<br>
-  return getContext().getCVContext().ad<wbr>dFile(FileNo, Filename);<br>
+bool MCStreamer::EmitCVFileDirectiv<wbr>e(unsigned FileNo, StringRef Filename,<br>
+                                     StringRef Checksum,<br>
+                                     unsigned ChecksumKind) {<br>
+  return getContext().getCVContext().ad<wbr>dFile(*this, FileNo, Filename, Checksum,<br>
+                                             ChecksumKind);<br>
 }<br>
<br>
 bool MCStreamer::EmitCVFuncIdDirect<wbr>ive(unsigned FunctionId) {<br>
<br>
Modified: llvm/trunk/test/DebugInfo/COFF<wbr>/inlining.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/inlining.ll?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/inlining.ll?rev=313374&<wbr>r1=313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/inlining.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/inlining.ll Fri Sep 15 11:20:28 2017<br>
@@ -49,11 +49,11 @@<br>
 ; ASM: .long   0<br>
 ; ASM: # Inlined function bar starts at t.cpp:8<br>
 ; ASM: .long   4098                    # Type index of inlined function<br>
-; ASM: .long   0                       # Offset into filechecksum table<br>
+; ASM: .cv_filechecksumoffset 1        # Offset into filechecksum table<br>
 ; ASM: .long   8                       # Starting line number<br>
 ; ASM: # Inlined function foo starts at t.cpp:2<br>
 ; ASM: .long   4099<br>
-; ASM: .long   0<br>
+; ASM: .cv_filechecksumoffset 1        # Offset into filechecksum table<br>
 ; ASM: .long   2<br>
 ; ASM: [[inline_end]]:<br>
<br>
@@ -72,6 +72,8 @@<br>
 ; ASM: .short  4430<br>
 ; ASM: .short  4430<br>
<br>
+; ASM: .cv_filechecksums<br>
+<br>
 ; ASM: .section .debug$T,"dr"<br>
 ; ASM: .long 4 # Debug section magic<br>
 ; ASM: # ArgList (0x1000) {<br>
<br>
Modified: llvm/trunk/test/DebugInfo/COFF<wbr>/multifile.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifile.ll?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/multifile.ll?rev=313374<wbr>&r1=313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/multifile.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/multifile.ll Fri Sep 15 11:20:28 2017<br>
@@ -18,10 +18,10 @@<br>
<br>
 ; X86-LABEL: _f:<br>
 ; X86:      # BB<br>
-; X86:      .cv_file 1 "D:\\one.c"<br>
+; X86:      .cv_file 1 "D:\\one.c" "70b51f534d80639d033ae92c6a856<wbr>af6" 1<br>
 ; X86:      .cv_loc 0 1 1 0 is_stmt 0 # one.c:1:0<br>
 ; X86:      calll   _g<br>
-; X86:      .cv_file 2 "D:\\two.c"<br>
+; X86:      .cv_file 2 "D:\\two.c" "70b51f534d80639d033ae92c6a856<wbr>af6" 1<br>
 ; X86:      .cv_loc 0 2 2 0 # two.c:2:0<br>
 ; X86:      calll   _g<br>
 ; X86:      .cv_loc 0 1 7 0 # one.c:7:0<br>
@@ -51,6 +51,28 @@<br>
 ; OBJ32-NEXT:   ProcEnd {<br>
 ; OBJ32:        }<br>
 ; OBJ32-NEXT: ]<br>
+; OBJ32:         Subsection [<br>
+; OBJ32:        SubSectionType: FileChecksums (0xF4)<br>
+; OBJ32-NEXT:   SubSectionSize: 0x50<br>
+; OBJ32-NEXT:   FileChecksum {<br>
+; OBJ32-NEXT:     Filename: D:\one.c (0x1)<br>
+; OBJ32-NEXT:     ChecksumSize: 0x20<br>
+; OBJ32-NEXT:     ChecksumKind: MD5 (0x1)<br>
+; OBJ32-NEXT:     ChecksumBytes (<br>
+; OBJ32-NEXT:       0000: 37306235 31663533 34643830 36333964  |70b51f534d80639d|<br>
+; OBJ32-NEXT:       0010: 30333361 65393263 36613835 36616636  |033ae92c6a856af6|<br>
+; OBJ32-NEXT:     )<br>
+; OBJ32-NEXT:   }<br>
+; OBJ32-NEXT:   FileChecksum {<br>
+; OBJ32-NEXT:     Filename: D:\two.c (0xA)<br>
+; OBJ32-NEXT:     ChecksumSize: 0x20<br>
+; OBJ32-NEXT:     ChecksumKind: MD5 (0x1)<br>
+; OBJ32-NEXT:     ChecksumBytes (<br>
+; OBJ32-NEXT:       0000: 37306235 31663533 34643830 36333964  |70b51f534d80639d|<br>
+; OBJ32-NEXT:       0010: 30333361 65393263 36613835 36616636  |033ae92c6a856af6|<br>
+; OBJ32-NEXT:     )<br>
+; OBJ32-NEXT:   }<br>
+; OBJ32-NEXT:  ]<br>
 ; OBJ32:      FunctionLineTable [<br>
 ; OBJ32-NEXT:   Name: _f<br>
 ; OBJ32-NEXT:   Flags: 0x0<br>
@@ -88,14 +110,14 @@<br>
<br>
 ; X64-LABEL: f:<br>
 ; X64-NEXT: .L{{.*}}:{{$}}<br>
-; X64:      .cv_file 1 "D:\\input.c"<br>
+; X64:      .cv_file 1 "D:\\input.c" "70b51f534d80639d033ae92c6a856<wbr>af6" 1<br>
 ; X64:      .cv_loc 0 1 3 0 is_stmt 0 # input.c:3:0<br>
 ; X64:      # BB<br>
 ; X64:      subq    $40, %rsp<br>
-; X64:      .cv_file 2 "D:\\one.c"<br>
+; X64:      .cv_file 2 "D:\\one.c" "70b51f534d80639d033ae92c6a856<wbr>af6" 1<br>
 ; X64:      .cv_loc 0 2 1 0 # one.c:1:0<br>
 ; X64:      callq   g<br>
-; X64:      .cv_file 3 "D:\\two.c"<br>
+; X64:      .cv_file 3 "D:\\two.c" "70b51f534d80639d033ae92c6a856<wbr>af6" 1<br>
 ; X64:      .cv_loc 0 3 2 0 # two.c:2:0<br>
 ; X64:      callq   g<br>
 ; X64:      .cv_loc 0 2 7 0 # one.c:7:0<br>
@@ -123,6 +145,37 @@<br>
 ; OBJ64-NEXT:   ProcEnd {<br>
 ; OBJ64:        }<br>
 ; OBJ64-NEXT: ]<br>
+; OBJ64:         Subsection [<br>
+; OBJ64:        SubSectionType: FileChecksums (0xF4)<br>
+; OBJ64-NEXT:   SubSectionSize: 0x78<br>
+; OBJ64-NEXT:   FileChecksum {<br>
+; OBJ64-NEXT:     Filename: D:\input.c (0x1)<br>
+; OBJ64-NEXT:     ChecksumSize: 0x20<br>
+; OBJ64-NEXT:     ChecksumKind: MD5 (0x1)<br>
+; OBJ64-NEXT:     ChecksumBytes (<br>
+; OBJ64-NEXT:       0000: 37306235 31663533 34643830 36333964  |70b51f534d80639d|<br>
+; OBJ64-NEXT:       0010: 30333361 65393263 36613835 36616636  |033ae92c6a856af6|<br>
+; OBJ64-NEXT:     )<br>
+; OBJ64-NEXT:   }<br>
+; OBJ64-NEXT:   FileChecksum {<br>
+; OBJ64-NEXT:     Filename: D:\one.c (0xC)<br>
+; OBJ64-NEXT:     ChecksumSize: 0x20<br>
+; OBJ64-NEXT:     ChecksumKind: MD5 (0x1)<br>
+; OBJ64-NEXT:     ChecksumBytes (<br>
+; OBJ64-NEXT:       0000: 37306235 31663533 34643830 36333964  |70b51f534d80639d|<br>
+; OBJ64-NEXT:       0010: 30333361 65393263 36613835 36616636  |033ae92c6a856af6|<br>
+; OBJ64-NEXT:     )<br>
+; OBJ64-NEXT:   }<br>
+; OBJ64-NEXT:   FileChecksum {<br>
+; OBJ64-NEXT:     Filename: D:\two.c (0x15)<br>
+; OBJ64-NEXT:     ChecksumSize: 0x20<br>
+; OBJ64-NEXT:     ChecksumKind: MD5 (0x1)<br>
+; OBJ64-NEXT:     ChecksumBytes (<br>
+; OBJ64-NEXT:       0000: 37306235 31663533 34643830 36333964  |70b51f534d80639d|<br>
+; OBJ64-NEXT:       0010: 30333361 65393263 36613835 36616636  |033ae92c6a856af6|<br>
+; OBJ64-NEXT:     )<br>
+; OBJ64-NEXT:   }<br>
+; OBJ64-NEXT:  ]<br>
 ; OBJ64:      FunctionLineTable [<br>
 ; OBJ64-NEXT:   Name: f<br>
 ; OBJ64-NEXT:   Flags: 0x0<br>
@@ -185,11 +238,11 @@ attributes #1 = { "less-precise-fpmad"="<br>
 !llvm.ident = !{!11}<br>
<br>
 !0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.5 ", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)<br>
-!1 = !DIFile(filename: "<unknown>", directory: "D:\5C")<br>
+!1 = !DIFile(filename: "<unknown>", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033a<wbr>e92c6a856af6")<br>
 !2 = !{}<br>
 !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2)<br>
-!5 = !DIFile(filename: "input.c", directory: "D:\5C")<br>
-!6 = !DIFile(filename: "input.c", directory: "D:C")<br>
+!5 = !DIFile(filename: "input.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033a<wbr>e92c6a856af6")<br>
+!6 = !DIFile(filename: "input.c", directory: "D:C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033a<wbr>e92c6a856af6")<br>
 !7 = !DISubroutineType(types: !8)<br>
 !8 = !{null}<br>
 !9 = !{i32 2, !"CodeView", i32 1}<br>
@@ -197,9 +250,9 @@ attributes #1 = { "less-precise-fpmad"="<br>
 !11 = !{!"clang version 3.5 "}<br>
 !12 = !DILocation(line: 1, scope: !13)<br>
 !13 = !DILexicalBlockFile(discrimina<wbr>tor: 0, file: !14, scope: !4)<br>
-!14 = !DIFile(filename: "one.c", directory: "D:\5C")<br>
+!14 = !DIFile(filename: "one.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033a<wbr>e92c6a856af6")<br>
 !15 = !DILocation(line: 2, scope: !16)<br>
 !16 = !DILexicalBlockFile(discrimina<wbr>tor: 0, file: !17, scope: !4)<br>
-!17 = !DIFile(filename: "two.c", directory: "D:\5C")<br>
+!17 = !DIFile(filename: "two.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum:"70b51f534d80639d033a<wbr>e92c6a856af6")<br>
 !18 = !DILocation(line: 7, scope: !13)<br>
 !19 = !DILocation(line: 8, scope: !13)<br>
<br>
Modified: llvm/trunk/test/DebugInfo/COFF<wbr>/simple.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/simple.ll?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/DebugInf<wbr>o/COFF/simple.ll?rev=313374&r1<wbr>=313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/DebugInfo/COFF<wbr>/simple.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/COFF<wbr>/simple.ll Fri Sep 15 11:20:28 2017<br>
@@ -17,7 +17,7 @@<br>
<br>
 ; X86-LABEL: _f:<br>
 ; X86:      # BB<br>
-; X86:      .cv_file 1 "D:\\test.c"<br>
+; X86:      .cv_file 1 "D:\\test.c" "f310ab26998ca831cbdf169e4eeca<wbr>cfa" 1<br>
 ; X86:      .cv_loc 0 1 4 2 is_stmt 0 # test.c:4:2<br>
 ; X86:      calll   _g<br>
 ; X86:      .cv_loc 0 1 5 0 # test.c:5:0<br>
@@ -85,6 +85,19 @@<br>
 ; OBJ32-NEXT:   ProcEnd {<br>
 ; OBJ32:        }<br>
 ; OBJ32-NEXT: ]<br>
+; OBJ32:       Subsection [<br>
+; OBJ32:         SubSectionType: FileChecksums (0xF4)<br>
+; OBJ32-NEXT:    SubSectionSize: 0x28<br>
+; OBJ32-NEXT:    FileChecksum {<br>
+; OBJ32-NEXT:      Filename: D:\test.c (0x1)<br>
+; OBJ32-NEXT:      ChecksumSize: 0x20<br>
+; OBJ32-NEXT:      ChecksumKind: MD5 (0x1)<br>
+; OBJ32-NEXT:      ChecksumBytes (<br>
+; OBJ32-NEXT:        0000: 66333130 61623236 39393863 61383331  |f310ab26998ca831|<br>
+; OBJ32-NEXT:        0010: 63626466 31363965 34656563 61636661  |cbdf169e4eecacfa|<br>
+; OBJ32-NEXT:      )<br>
+; OBJ32-NEXT:    }<br>
+; OBJ32-NEXT:  ]<br>
 ; OBJ32:      FunctionLineTable [<br>
 ; OBJ32-NEXT:   Name: _f<br>
 ; OBJ32-NEXT:   Flags: 0x1<br>
@@ -110,7 +123,7 @@<br>
<br>
 ; X64-LABEL: f:<br>
 ; X64-NEXT: .L{{.*}}:{{$}}<br>
-; X64:      .cv_file 1 "D:\\test.c"<br>
+; X64:      .cv_file 1 "D:\\test.c" "f310ab26998ca831cbdf169e4eeca<wbr>cfa" 1<br>
 ; X64:      .cv_loc 0 1 3 0 is_stmt 0 # test.c:3:0<br>
 ; X64:      # BB<br>
 ; X64:      subq    $40, %rsp<br>
@@ -182,6 +195,19 @@<br>
 ; OBJ64-NEXT:   ProcEnd {<br>
 ; OBJ64:        }<br>
 ; OBJ64-NEXT: ]<br>
+; OBJ64:       Subsection [<br>
+; OBJ64:         SubSectionType: FileChecksums (0xF4)<br>
+; OBJ64-NEXT:    SubSectionSize: 0x28<br>
+; OBJ64-NEXT:    FileChecksum {<br>
+; OBJ64-NEXT:      Filename: D:\test.c (0x1)<br>
+; OBJ64-NEXT:      ChecksumSize: 0x20<br>
+; OBJ64-NEXT:      ChecksumKind: MD5 (0x1)<br>
+; OBJ64-NEXT:      ChecksumBytes (<br>
+; OBJ64-NEXT:        0000: 66333130 61623236 39393863 61383331  |f310ab26998ca831|<br>
+; OBJ64-NEXT:        0010: 63626466 31363965 34656563 61636661  |cbdf169e4eecacfa|<br>
+; OBJ64-NEXT:      )<br>
+; OBJ64-NEXT:    }<br>
+; OBJ64-NEXT:  ]<br>
 ; OBJ64:      FunctionLineTable [<br>
 ; OBJ64-NEXT:   Name: f<br>
 ; OBJ64-NEXT:   Flags: 0x1<br>
@@ -232,8 +258,8 @@ attributes #1 = { "less-precise-fpmad"="<br>
 !1 = !DIFile(filename: "<unknown>", directory: "D:\5C")<br>
 !2 = !{}<br>
 !4 = distinct !DISubprogram(name: "f", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !5, scope: !6, type: !7, variables: !2)<br>
-!5 = !DIFile(filename: "test.c", directory: "D:\5C")<br>
-!6 = !DIFile(filename: "test.c", directory: "D:C")<br>
+!5 = !DIFile(filename: "test.c", directory: "D:\5C", checksumkind: CSK_MD5, checksum: "f310ab26998ca831cbdf169e4eeca<wbr>cfa")<br>
+!6 = !DIFile(filename: "test.c", directory: "D:C", checksumkind: CSK_MD5, checksum: "f310ab26998ca831cbdf169e4eeca<wbr>cfa")<br>
 !7 = !DISubroutineType(types: !8)<br>
 !8 = !{null}<br>
 !9 = !{i32 2, !"CodeView", i32 1}<br>
<br>
Modified: llvm/trunk/test/MC/AArch64/cof<wbr>f-debug.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/coff-debug.ll?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/MC/AArch<wbr>64/coff-debug.ll?rev=313374&r1<wbr>=313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/MC/AArch64/cof<wbr>f-debug.ll (original)<br>
+++ llvm/trunk/test/MC/AArch64/cof<wbr>f-debug.ll Fri Sep 15 11:20:28 2017<br>
@@ -103,7 +103,7 @@ attributes #0 = { noinline nounwind optn<br>
 ; CHECK:     SubSectionType: FileChecksums (0xF4)<br>
 ; CHECK:     FileChecksum {<br>
 ; CHECK:       ChecksumSize: 0x0<br>
-; CHECK:       ChecksumKind: None (0x0)<br>
+; CHECK:       ChecksumKind: MD5 (0x1)<br>
 ; CHECK:       ChecksumBytes: ()<br>
 ; CHECK:     }<br>
 ; CHECK:   ]<br>
<br>
Modified: llvm/trunk/unittests/IR/Metada<wbr>taTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/MetadataTest.cpp?rev=313374&r1=313373&r2=313374&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/unittests/IR/<wbr>MetadataTest.cpp?rev=313374&r1<wbr>=313373&r2=313374&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/unittests/IR/Metada<wbr>taTest.cpp (original)<br>
+++ llvm/trunk/unittests/IR/Metada<wbr>taTest.cpp Fri Sep 15 11:20:28 2017<br>
@@ -1383,7 +1383,8 @@ TEST_F(DIFileTest, get) {<br>
<br>
   EXPECT_NE(N, DIFile::get(Context, "other", Directory, CSKind, Checksum));<br>
   EXPECT_NE(N, DIFile::get(Context, Filename, "other", CSKind, Checksum));<br>
-  EXPECT_NE(N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum));<br>
+  EXPECT_NE(<br>
+      N, DIFile::get(Context, Filename, Directory, DIFile::CSK_SHA1, Checksum));<br>
   EXPECT_NE(N, DIFile::get(Context, Filename, Directory));<br>
<br>
   TempDIFile Temp = N->clone();<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div></div>