[llvm] r259130 - Reland "[CodeView] Use assembler directives for line tables"

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 28 16:49:42 PST 2016


Author: rnk
Date: Thu Jan 28 18:49:42 2016
New Revision: 259130

URL: http://llvm.org/viewvc/llvm-project?rev=259130&view=rev
Log:
Reland "[CodeView] Use assembler directives for line tables"

This reverts commit r259126 and relands r259117.

This time with updated library dependencies.

Added:
    llvm/trunk/include/llvm/MC/MCCodeView.h
    llvm/trunk/lib/MC/MCCodeView.cpp
    llvm/trunk/test/MC/COFF/cv-loc.s
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h
    llvm/trunk/include/llvm/MC/MCContext.h
    llvm/trunk/include/llvm/MC/MCObjectStreamer.h
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/include/llvm/MC/StringTableBuilder.h
    llvm/trunk/include/llvm/Support/COFF.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
    llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt
    llvm/trunk/lib/MC/CMakeLists.txt
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCContext.cpp
    llvm/trunk/lib/MC/MCObjectStreamer.cpp
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/lib/MC/MCStreamer.cpp
    llvm/trunk/lib/MC/StringTableBuilder.cpp
    llvm/trunk/test/DebugInfo/COFF/asm.ll
    llvm/trunk/test/DebugInfo/COFF/multifile.ll
    llvm/trunk/test/DebugInfo/COFF/multifunction.ll
    llvm/trunk/test/DebugInfo/COFF/simple.ll
    llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
    llvm/trunk/unittests/MC/StringTableBuilderTest.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h Thu Jan 28 18:49:42 2016
@@ -21,16 +21,19 @@ using llvm::support::ulittle32_t;
 
 class LineInfo {
 public:
-  static const uint32_t AlwaysStepIntoLineNumber = 0xfeefee;
-  static const uint32_t NeverStepIntoLineNumber = 0xf00f00;
+  enum : uint32_t {
+    AlwaysStepIntoLineNumber = 0xfeefee,
+    NeverStepIntoLineNumber = 0xf00f00
+  };
+
+  enum : int { EndLineDeltaShift = 24 };
+
+  enum : uint32_t {
+    StartLineMask = 0x00ffffff,
+    EndLineDeltaMask = 0x7f000000,
+    StatementFlag = 0x80000000u
+  };
 
-private:
-  static const uint32_t StartLineMask = 0x00ffffff;
-  static const uint32_t EndLineDeltaMask = 0x7f000000;
-  static const int EndLineDeltaShift = 24;
-  static const uint32_t StatementFlag = 0x80000000u;
-
-public:
   LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement);
 
   uint32_t getStartLine() const { return LineData & StartLineMask; }
@@ -151,6 +154,10 @@ struct FileChecksum {
   // Checksum bytes follow.
 };
 
+enum LineFlags : uint32_t {
+  HaveColumns = 1, // CV_LINES_HAVE_COLUMNS
+};
+
 } // namespace codeview
 } // namespace llvm
 

Added: llvm/trunk/include/llvm/MC/MCCodeView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCCodeView.h?rev=259130&view=auto
==============================================================================
--- llvm/trunk/include/llvm/MC/MCCodeView.h (added)
+++ llvm/trunk/include/llvm/MC/MCCodeView.h Thu Jan 28 18:49:42 2016
@@ -0,0 +1,162 @@
+//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Holds state from .cv_file and .cv_loc directives for later emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCCODEVIEW_H
+#define LLVM_MC_MCCODEVIEW_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCFragment.h"
+#include <map>
+#include <vector>
+
+namespace llvm {
+class MCContext;
+class MCObjectStreamer;
+class MCStreamer;
+
+/// \brief Instances of this class represent the information from a
+/// .cv_loc directive.
+class MCCVLoc {
+  uint32_t FunctionId;
+  uint32_t FileNum;
+  uint32_t Line;
+  uint16_t Column;
+  uint16_t PrologueEnd : 1;
+  uint16_t IsStmt : 1;
+
+private: // MCContext manages these
+  friend class MCContext;
+  MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned column,
+          bool prologueend, bool isstmt)
+      : FunctionId(functionid), FileNum(fileNum), Line(line), Column(column),
+        PrologueEnd(prologueend), IsStmt(isstmt) {}
+
+  // Allow the default copy constructor and assignment operator to be used
+  // for an MCCVLoc object.
+
+public:
+  unsigned getFunctionId() const { return FunctionId; }
+
+  /// \brief Get the FileNum of this MCCVLoc.
+  unsigned getFileNum() const { return FileNum; }
+
+  /// \brief Get the Line of this MCCVLoc.
+  unsigned getLine() const { return Line; }
+
+  /// \brief Get the Column of this MCCVLoc.
+  unsigned getColumn() const { return Column; }
+
+  bool isPrologueEnd() const { return PrologueEnd; }
+  bool isStmt() const { return IsStmt; }
+
+  void setFunctionId(unsigned FID) { FunctionId = FID; }
+
+  /// \brief Set the FileNum of this MCCVLoc.
+  void setFileNum(unsigned fileNum) { FileNum = fileNum; }
+
+  /// \brief Set the Line of this MCCVLoc.
+  void setLine(unsigned line) { Line = line; }
+
+  /// \brief Set the Column of this MCCVLoc.
+  void setColumn(unsigned column) {
+    assert(column <= UINT16_MAX);
+    Column = column;
+  }
+
+  void setPrologueEnd(bool PE) { PrologueEnd = PE; }
+  void setIsStmt(bool IS) { IsStmt = IS; }
+};
+
+/// \brief Instances of this class represent the line information for
+/// the CodeView line table entries.  Which is created after a machine
+/// instruction is assembled and uses an address from a temporary label
+/// created at the current address in the current section and the info from
+/// the last .cv_loc directive seen as stored in the context.
+class MCCVLineEntry : public MCCVLoc {
+  MCSymbol *Label;
+
+private:
+  // Allow the default copy constructor and assignment operator to be used
+  // for an MCCVLineEntry object.
+
+public:
+  // Constructor to create an MCCVLineEntry given a symbol and the dwarf loc.
+  MCCVLineEntry(MCSymbol *label, const MCCVLoc loc)
+      : MCCVLoc(loc), Label(label) {}
+
+  MCSymbol *getLabel() const { return Label; }
+
+  // This is called when an instruction is assembled into the specified
+  // section and if there is information from the last .cv_loc directive that
+  // has yet to have a line entry made for it is made.
+  static void Make(MCObjectStreamer *MCOS);
+};
+
+/// Holds state from .cv_file and .cv_loc directives for later emission.
+class CodeViewContext {
+public:
+  CodeViewContext();
+  ~CodeViewContext();
+
+  bool isValidFileNumber(unsigned FileNumber) const;
+  bool addFile(unsigned FileNumber, StringRef Filename);
+  ArrayRef<StringRef> getFilenames() { return Filenames; }
+
+  /// \brief Add a line entry.
+  void addLineEntry(const MCCVLineEntry &LineEntry) {
+    MCCVLines[LineEntry.getFunctionId()].push_back(LineEntry);
+  }
+
+  ArrayRef<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) {
+    assert(MCCVLines.find(FuncId) != MCCVLines.end());
+    return MCCVLines.find(FuncId)->second;
+  }
+
+  /// Emits a line table substream.
+  void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
+                                const MCSymbol *FuncBegin,
+                                const MCSymbol *FuncEnd);
+
+  /// Emits the string table substream.
+  void emitStringTable(MCObjectStreamer &OS);
+
+  /// Emits the file checksum substream.
+  void emitFileChecksums(MCObjectStreamer &OS);
+
+private:
+  /// Map from string to string table offset.
+  StringMap<unsigned> StringTable;
+
+  /// The fragment that ultimately holds our strings.
+  MCDataFragment *StrTabFragment = nullptr;
+  bool InsertedStrTabFragment = false;
+
+  MCDataFragment *getStringTableFragment();
+
+  /// Add something to the string table.
+  StringRef addToStringTable(StringRef S);
+
+  /// Get a string table offset.
+  unsigned getStringTableOffset(StringRef S);
+
+  /// An array of absolute paths. Eventually this may include the file checksum.
+  SmallVector<StringRef, 4> Filenames;
+
+  /// A collection of MCDwarfLineEntry for each section.
+  std::map<int, std::vector<MCCVLineEntry>> MCCVLines;
+};
+
+} // end namespace llvm
+#endif

Modified: llvm/trunk/include/llvm/MC/MCContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCContext.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCContext.h (original)
+++ llvm/trunk/include/llvm/MC/MCContext.h Thu Jan 28 18:49:42 2016
@@ -16,6 +16,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCCodeView.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/SectionKind.h"
@@ -42,6 +43,7 @@ namespace llvm {
   class MCSectionMachO;
   class MCSectionELF;
   class MCSectionCOFF;
+  class CodeViewContext;
 
   /// Context object for machine code objects.  This class owns all of the
   /// sections that it creates.
@@ -66,6 +68,8 @@ namespace llvm {
     /// The MCObjectFileInfo for this target.
     const MCObjectFileInfo *MOFI;
 
+    std::unique_ptr<CodeViewContext> CVContext;
+
     /// Allocator object used for creating machine code objects.
     ///
     /// We use a bump pointer allocator to avoid the need to track all allocated
@@ -135,6 +139,10 @@ namespace llvm {
     MCDwarfLoc CurrentDwarfLoc;
     bool DwarfLocSeen;
 
+    /// The current CodeView line information from the last .cv_loc directive.
+    MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);
+    bool CVLocSeen = false;
+
     /// Generate dwarf debugging info for assembly source files.
     bool GenDwarfForAssembly;
 
@@ -237,6 +245,8 @@ namespace llvm {
 
     const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; }
 
+    CodeViewContext &getCVContext();
+
     void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; }
     void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; }
 
@@ -505,6 +515,35 @@ namespace llvm {
 
     /// @}
 
+
+    /// \name CodeView Management
+    /// @{
+
+    /// Creates an entry in the cv file table.
+    unsigned getCVFile(StringRef FileName, unsigned FileNumber);
+
+    /// Saves the information from the currently parsed .cv_loc directive
+    /// and sets CVLocSeen.  When the next instruction is assembled an entry
+    /// in the line number table with this information and the address of the
+    /// instruction will be created.
+    void setCurrentCVLoc(unsigned FunctionId, unsigned FileNo, unsigned Line,
+                         unsigned Column, bool PrologueEnd, bool IsStmt) {
+      CurrentCVLoc.setFunctionId(FunctionId);
+      CurrentCVLoc.setFileNum(FileNo);
+      CurrentCVLoc.setLine(Line);
+      CurrentCVLoc.setColumn(Column);
+      CurrentCVLoc.setPrologueEnd(PrologueEnd);
+      CurrentCVLoc.setIsStmt(IsStmt);
+      CVLocSeen = true;
+    }
+    void clearCVLocSeen() { CVLocSeen = false; }
+
+    bool getCVLocSeen() { return CVLocSeen; }
+    const MCCVLoc &getCurrentCVLoc() { return CurrentCVLoc; }
+
+    bool isValidCVFileNumber(unsigned FileNumber);
+    /// @}
+
     char *getSecureLogFile() { return SecureLogFile; }
     raw_fd_ostream *getSecureLog() { return SecureLog.get(); }
     bool getSecureLogUsed() { return SecureLogUsed; }

Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Thu Jan 28 18:49:42 2016
@@ -59,7 +59,6 @@ public:
   void EmitFrames(MCAsmBackend *MAB);
   void EmitCFISections(bool EH, bool Debug) override;
 
-protected:
   MCFragment *getCurrentFragment() const;
 
   void insert(MCFragment *F) {
@@ -73,6 +72,7 @@ protected:
   /// fragment is not a data fragment.
   MCDataFragment *getOrCreateDataFragment();
 
+protected:
   bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
 
   /// If any labels have been emitted but not assigned fragments, ensure that
@@ -122,6 +122,13 @@ public:
                                 unsigned PointerSize);
   void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
                                  const MCSymbol *Label);
+  void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
+                          unsigned Column, bool PrologueEnd, bool IsStmt,
+                          StringRef FileName) override;
+  void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *Begin,
+                                const MCSymbol *End) override;
+  void EmitCVStringTableDirective() override;
+  void EmitCVFileChecksumsDirective() override;
   void EmitGPRel32Value(const MCExpr *Value) override;
   void EmitGPRel64Value(const MCExpr *Value) override;
   bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Thu Jan 28 18:49:42 2016
@@ -640,6 +640,27 @@ public:
                                      unsigned Isa, unsigned Discriminator,
                                      StringRef FileName);
 
+  /// \brief Associate a filename with a specified logical file number.  This
+  /// implements the '.cv_file 4 "foo.c"' assembler directive.
+  virtual unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename);
+
+  /// \brief This implements the CodeView '.cv_loc' assembler directive.
+  virtual void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+                                  unsigned Line, unsigned Column,
+                                  bool PrologueEnd, bool IsStmt,
+                                  StringRef FileName);
+
+  /// \brief This implements the CodeView '.cv_linetable' assembler directive.
+  virtual void EmitCVLinetableDirective(unsigned FunctionId,
+                                        const MCSymbol *FnStart,
+                                        const MCSymbol *FnEnd);
+
+  /// \brief This implements the CodeView '.cv_stringtable' assembler directive.
+  virtual void EmitCVStringTableDirective() {}
+
+  /// \brief This implements the CodeView '.cv_filechecksums' assembler directive.
+  virtual void EmitCVFileChecksumsDirective() {}
+
   /// Emit the absolute difference between two symbols.
   ///
   /// \pre Offset of \c Hi is greater than the offset \c Lo.

Modified: llvm/trunk/include/llvm/MC/StringTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/StringTableBuilder.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/StringTableBuilder.h (original)
+++ llvm/trunk/include/llvm/MC/StringTableBuilder.h Thu Jan 28 18:49:42 2016
@@ -27,6 +27,8 @@ private:
   size_t Size = 0;
   Kind K;
 
+  void finalizeStringTable(bool Optimize);
+
 public:
   StringTableBuilder(Kind K);
 
@@ -39,6 +41,10 @@ public:
   /// be added after this point.
   void finalize();
 
+  /// Finalize the string table without reording it. In this mode, offsets
+  /// returned by add will still be valid.
+  void finalizeInOrder();
+
   /// \brief Retrieve the string table data. Can only be used after the table
   /// is finalized.
   StringRef data() const {

Modified: llvm/trunk/include/llvm/Support/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/COFF.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/COFF.h (original)
+++ llvm/trunk/include/llvm/Support/COFF.h Thu Jan 28 18:49:42 2016
@@ -656,17 +656,7 @@ namespace COFF {
     }
   };
 
-  enum CodeViewLine : unsigned {
-    CVL_LineNumberStartBits = 24,
-    CVL_LineNumberEndDeltaBits = 7,
-    CVL_LineNumberEndDeltaMask = (1U << CVL_LineNumberEndDeltaBits) - 1,
-    CVL_MaxLineNumber = (1U << CVL_LineNumberStartBits) - 1,
-    CVL_IsStatement = 1U << 31,
-    CVL_MaxColumnNumber = UINT16_MAX,
-  };
-
   enum CodeViewIdentifiers {
-    DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1,
     DEBUG_SECTION_MAGIC = 0x4,
   };
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Thu Jan 28 18:49:42 2016
@@ -13,6 +13,7 @@
 
 #include "CodeViewDebug.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCSymbol.h"
@@ -74,6 +75,18 @@ StringRef CodeViewDebug::getFullFilepath
   return Filepath;
 }
 
+unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
+  unsigned NextId = FileIdMap.size() + 1;
+  auto Insertion = FileIdMap.insert(std::make_pair(F, NextId));
+  if (Insertion.second) {
+    // We have to compute the full filepath and emit a .cv_file directive.
+    StringRef FullPath = getFullFilepath(F);
+    NextId = Asm->OutStreamer->EmitCVFileDirective(NextId, FullPath);
+    assert(NextId == FileIdMap.size() && ".cv_file directive failed");
+  }
+  return Insertion.first->second;
+}
+
 void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
                                         const MachineFunction *MF) {
   // Skip this instruction if it has the same location as the previous one.
@@ -85,15 +98,26 @@ void CodeViewDebug::maybeRecordLocation(
     return;
 
   // Skip this line if it is longer than the maximum we can record.
-  if (DL.getLine() > COFF::CVL_MaxLineNumber)
+  LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true);
+  if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
+      LI.isNeverStepInto())
     return;
 
-  CurFn->LastLoc = DL;
+  ColumnInfo CI(DL.getCol(), /*EndColumn=*/0);
+  if (CI.getStartColumn() != DL.getCol())
+    return;
 
-  MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol();
-  Asm->OutStreamer->EmitLabel(MCL);
-  CurFn->Instrs.push_back(MCL);
-  LabelsAndLocs[MCL] = DL;
+  if (!CurFn->HaveLineInfo)
+    CurFn->HaveLineInfo = true;
+  unsigned FileId = 0;
+  if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile())
+    FileId = CurFn->LastFileId;
+  else
+    FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
+  CurFn->LastLoc = DL;
+  Asm->OutStreamer->EmitCVLocDirective(CurFn->FuncId, FileId, DL.getLine(),
+                                       DL.getCol(), /*PrologueEnd=*/false,
+                                       /*IsStmt=*/false, DL->getFilename());
 }
 
 CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
@@ -128,39 +152,17 @@ void CodeViewDebug::endModule() {
   // of the payload followed by the payload itself.  The subsections are 4-byte
   // aligned.
 
-  // Emit per-function debug information.  This code is extracted into a
-  // separate function for readability.
-  for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
-    emitDebugInfoForFunction(VisitedFunctions[I]);
+  // Emit per-function debug information.
+  for (auto &P : FnDebugInfo)
+    emitDebugInfoForFunction(P.first, P.second);
 
   // This subsection holds a file index to offset in string table table.
   Asm->OutStreamer->AddComment("File index to string table offset subsection");
-  Asm->EmitInt32(unsigned(ModuleSubstreamKind::FileChecksums));
-  size_t NumFilenames = FileNameRegistry.Infos.size();
-  Asm->EmitInt32(8 * NumFilenames);
-  for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
-    StringRef Filename = FileNameRegistry.Filenames[I];
-    // For each unique filename, just write its offset in the string table.
-    Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
-    // The function name offset is not followed by any additional data.
-    Asm->EmitInt32(0);
-  }
+  Asm->OutStreamer->EmitCVFileChecksumsDirective();
 
   // This subsection holds the string table.
   Asm->OutStreamer->AddComment("String table");
-  Asm->EmitInt32(unsigned(ModuleSubstreamKind::StringTable));
-  Asm->EmitInt32(FileNameRegistry.LastOffset);
-  // The payload starts with a null character.
-  Asm->EmitInt8(0);
-
-  for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
-    // Just emit unique filenames one by one, separated by a null character.
-    Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
-    Asm->EmitInt8(0);
-  }
-
-  // No more subsections. Fill with zeros to align the end of the section by 4.
-  Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
+  Asm->OutStreamer->EmitCVStringTableDirective();
 
   clear();
 }
@@ -177,21 +179,13 @@ static void EmitLabelDiff(MCStreamer &St
   Streamer.EmitValue(AddrDelta, Size);
 }
 
-static const DIFile *getFileFromLoc(DebugLoc DL) {
-  return DL.get()->getScope()->getFile();
-}
-
-void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) {
+void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
+                                             FunctionInfo &FI) {
   // For each function there is a separate subsection
   // which holds the PC to file:line table.
   const MCSymbol *Fn = Asm->getSymbol(GV);
   assert(Fn);
 
-  const FunctionInfo &FI = FnDebugInfo[GV];
-  if (FI.Instrs.empty())
-    return;
-  assert(FI.End && "Don't know where the function ends?");
-
   StringRef FuncName;
   if (auto *SP = getDISubprogram(GV))
     FuncName = SP->getDisplayName();
@@ -238,102 +232,8 @@ void CodeViewDebug::emitDebugInfoForFunc
   // Every subsection must be aligned to a 4-byte boundary.
   Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
 
-  // PCs/Instructions are grouped into segments sharing the same filename.
-  // Pre-calculate the lengths (in instructions) of these segments and store
-  // them in a map for convenience.  Each index in the map is the sequential
-  // number of the respective instruction that starts a new segment.
-  DenseMap<size_t, size_t> FilenameSegmentLengths;
-  size_t LastSegmentEnd = 0;
-  const DIFile *PrevFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[0]]);
-  for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
-    const DIFile *CurFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
-    if (PrevFile == CurFile)
-      continue;
-    FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
-    LastSegmentEnd = J;
-    PrevFile = CurFile;
-  }
-  FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
-
-  // Emit a line table subsection, required to do PC-to-file:line lookup.
-  Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName));
-  Asm->EmitInt32(unsigned(ModuleSubstreamKind::Lines));
-  MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(),
-           *LineTableEnd = Asm->MMI->getContext().createTempSymbol();
-  EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd);
-  Asm->OutStreamer->EmitLabel(LineTableBegin);
-
-  // Identify the function this subsection is for.
-  Asm->OutStreamer->EmitCOFFSecRel32(Fn);
-  Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
-  // Insert flags after a 16-bit section index.
-  Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS);
-
-  // Length of the function's code, in bytes.
-  EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
-
-  // PC-to-linenumber lookup table:
-  MCSymbol *FileSegmentEnd = nullptr;
-
-  // The start of the last segment:
-  size_t LastSegmentStart = 0;
-
-  auto FinishPreviousChunk = [&] {
-    if (!FileSegmentEnd)
-      return;
-    for (size_t ColSegI = LastSegmentStart,
-                ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart];
-         ColSegI != ColSegEnd; ++ColSegI) {
-      unsigned ColumnNumber = LabelsAndLocs[FI.Instrs[ColSegI]].getCol();
-      // Truncate the column number if it is longer than the maximum we can
-      // record.
-      if (ColumnNumber > COFF::CVL_MaxColumnNumber)
-        ColumnNumber = 0;
-      Asm->EmitInt16(ColumnNumber); // Start column
-      Asm->EmitInt16(0);            // End column
-    }
-    Asm->OutStreamer->EmitLabel(FileSegmentEnd);
-  };
-
-  for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
-    MCSymbol *Instr = FI.Instrs[J];
-    assert(LabelsAndLocs.count(Instr));
-
-    if (FilenameSegmentLengths.count(J)) {
-      // We came to a beginning of a new filename segment.
-      FinishPreviousChunk();
-      const DIFile *File = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
-      StringRef CurFilename = getFullFilepath(File);
-      size_t IndexInFileTable = FileNameRegistry.add(CurFilename);
-      // Each segment starts with the offset of the filename
-      // in the string table.
-      Asm->OutStreamer->AddComment(
-          "Segment for file '" + Twine(CurFilename) + "' begins");
-      MCSymbol *FileSegmentBegin = Asm->MMI->getContext().createTempSymbol();
-      Asm->OutStreamer->EmitLabel(FileSegmentBegin);
-      Asm->EmitInt32(8 * IndexInFileTable);
-
-      // Number of PC records in the lookup table.
-      size_t SegmentLength = FilenameSegmentLengths[J];
-      Asm->EmitInt32(SegmentLength);
-
-      // Full size of the segment for this filename, including the prev two
-      // records.
-      FileSegmentEnd = Asm->MMI->getContext().createTempSymbol();
-      EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
-      LastSegmentStart = J;
-    }
-
-    // The first PC with the given linenumber and the linenumber itself.
-    EmitLabelDiff(*Asm->OutStreamer, Fn, Instr);
-    uint32_t LineNumber = LabelsAndLocs[Instr].getLine();
-    assert(LineNumber <= COFF::CVL_MaxLineNumber);
-    uint32_t LineData = LineNumber | COFF::CVL_IsStatement;
-    Asm->EmitInt32(LineData);
-  }
-
-  FinishPreviousChunk();
-  Asm->OutStreamer->EmitLabel(LineTableEnd);
+  // We have an assembler directive that takes care of the whole line table.
+  Asm->OutStreamer->EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
 }
 
 void CodeViewDebug::beginFunction(const MachineFunction *MF) {
@@ -344,8 +244,8 @@ void CodeViewDebug::beginFunction(const
 
   const Function *GV = MF->getFunction();
   assert(FnDebugInfo.count(GV) == false);
-  VisitedFunctions.push_back(GV);
   CurFn = &FnDebugInfo[GV];
+  CurFn->FuncId = NextFuncId++;
 
   // Find the end of the function prolog.
   // FIXME: is there a simpler a way to do this? Can we just search
@@ -384,9 +284,9 @@ void CodeViewDebug::endFunction(const Ma
   assert(FnDebugInfo.count(GV));
   assert(CurFn == &FnDebugInfo[GV]);
 
-  if (CurFn->Instrs.empty()) {
+  // Don't emit anything if we don't have any line tables.
+  if (!CurFn->HaveLineInfo) {
     FnDebugInfo.erase(GV);
-    VisitedFunctions.pop_back();
   } else {
     CurFn->End = Asm->getFunctionEnd();
   }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.h Thu Jan 28 18:49:42 2016
@@ -37,72 +37,38 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDe
   // to the end of the function.
   struct FunctionInfo {
     DebugLoc LastLoc;
-    SmallVector<MCSymbol *, 10> Instrs;
-    MCSymbol *End;
-    FunctionInfo() : End(nullptr) {}
+    MCSymbol *End = nullptr;
+    unsigned FuncId = 0;
+    unsigned LastFileId;
+    bool HaveLineInfo = false;
   };
   FunctionInfo *CurFn;
 
-  typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
-  FnDebugInfoTy FnDebugInfo;
-  // Store the functions we've visited in a vector so we can maintain a stable
-  // order while emitting subsections.
-  SmallVector<const Function *, 10> VisitedFunctions;
-
-  DenseMap<MCSymbol *, DebugLoc> LabelsAndLocs;
-
-  // FileNameRegistry - Manages filenames observed while generating debug info
-  // by filtering out duplicates and bookkeeping the offsets in the string
-  // table to be generated.
-  struct FileNameRegistryTy {
-    SmallVector<StringRef, 10> Filenames;
-    struct PerFileInfo {
-      size_t FilenameID, StartOffset;
-    };
-    StringMap<PerFileInfo> Infos;
-
-    // The offset in the string table where we'll write the next unique
-    // filename.
-    size_t LastOffset;
-
-    FileNameRegistryTy() {
-      clear();
-    }
-
-    // Add Filename to the registry, if it was not observed before.
-    size_t add(StringRef Filename) {
-      size_t OldSize = Infos.size();
-      bool Inserted;
-      StringMap<PerFileInfo>::iterator It;
-      std::tie(It, Inserted) = Infos.insert(
-          std::make_pair(Filename, PerFileInfo{OldSize, LastOffset}));
-      if (Inserted) {
-        LastOffset += Filename.size() + 1;
-        Filenames.push_back(Filename);
-      }
-      return It->second.FilenameID;
-    }
-
-    void clear() {
-      LastOffset = 1;
-      Infos.clear();
-      Filenames.clear();
-    }
-  } FileNameRegistry;
+  unsigned NextFuncId = 0;
+
+  /// Remember some debug info about each function. Keep it in a stable order to
+  /// emit at the end of the TU.
+  MapVector<const Function *, FunctionInfo> FnDebugInfo;
+
+  /// Map from DIFile to .cv_file id.
+  DenseMap<const DIFile *, unsigned> FileIdMap;
 
   typedef std::map<const DIFile *, std::string> FileToFilepathMapTy;
   FileToFilepathMapTy FileToFilepathMap;
   StringRef getFullFilepath(const DIFile *S);
 
+  unsigned maybeRecordFile(const DIFile *F);
+
   void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);
 
   void clear() {
     assert(CurFn == nullptr);
-    FileNameRegistry.clear();
-    LabelsAndLocs.clear();
+    FileIdMap.clear();
+    FnDebugInfo.clear();
+    FileToFilepathMap.clear();
   }
 
-  void emitDebugInfoForFunction(const Function *GV);
+  void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
 
 public:
   CodeViewDebug(AsmPrinter *Asm);

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/LLVMBuild.txt Thu Jan 28 18:49:42 2016
@@ -19,4 +19,4 @@
 type = Library
 name = AsmPrinter
 parent = Libraries
-required_libraries = Analysis CodeGen Core MC MCParser Support Target TransformUtils
+required_libraries = Analysis CodeGen Core DebugInfoCodeView MC MCParser Support Target TransformUtils

Modified: llvm/trunk/lib/MC/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/CMakeLists.txt?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/CMakeLists.txt (original)
+++ llvm/trunk/lib/MC/CMakeLists.txt Thu Jan 28 18:49:42 2016
@@ -10,6 +10,7 @@ add_llvm_library(LLVMMC
   MCAssembler.cpp
   MCCodeEmitter.cpp
   MCCodeGenInfo.cpp
+  MCCodeView.cpp
   MCContext.cpp
   MCDwarf.cpp
   MCELFObjectTargetWriter.cpp

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Thu Jan 28 18:49:42 2016
@@ -199,6 +199,15 @@ public:
                              StringRef FileName) override;
   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
 
+  unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+  void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
+                          unsigned Column, bool PrologueEnd, bool IsStmt,
+                          StringRef FileName) override;
+  void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
+                                const MCSymbol *FnEnd) override;
+  void EmitCVStringTableDirective() override;
+  void EmitCVFileChecksumsDirective() override;
+
   void EmitIdent(StringRef IdentString) override;
   void EmitCFISections(bool EH, bool Debug) override;
   void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
@@ -954,6 +963,69 @@ MCSymbol *MCAsmStreamer::getDwarfLineTab
   return MCStreamer::getDwarfLineTableSymbol(0);
 }
 
+unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo,
+                                            StringRef Filename) {
+  if (!getContext().getCVFile(Filename, FileNo))
+    return 0;
+
+  OS << "\t.cv_file\t" << FileNo << ' ';
+
+  PrintQuotedString(Filename, OS);
+  EmitEOL();
+
+  return FileNo;
+}
+
+void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+                                       unsigned Line, unsigned Column,
+                                       bool PrologueEnd, bool IsStmt,
+                                       StringRef FileName) {
+  OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
+     << Column;
+  if (PrologueEnd)
+    OS << " prologue_end";
+
+  unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt();
+  if (IsStmt != OldIsStmt) {
+    OS << " is_stmt ";
+
+    if (IsStmt)
+      OS << "1";
+    else
+      OS << "0";
+  }
+
+  if (IsVerboseAsm) {
+    OS.PadToColumn(MAI->getCommentColumn());
+    OS << MAI->getCommentString() << ' ' << FileName << ':'
+       << Line << ':' << Column;
+  }
+  EmitEOL();
+  this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
+                                       PrologueEnd, IsStmt, FileName);
+}
+
+void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+                                             const MCSymbol *FnStart,
+                                             const MCSymbol *FnEnd) {
+  OS << "\t.cv_linetable\t" << FunctionId << ", ";
+  FnStart->print(OS, MAI);
+  OS << ", ";
+  FnEnd->print(OS, MAI);
+  EmitEOL();
+  this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
+}
+
+void MCAsmStreamer::EmitCVStringTableDirective() {
+  OS << "\t.cv_stringtable";
+  EmitEOL();
+}
+
+void MCAsmStreamer::EmitCVFileChecksumsDirective() {
+  OS << "\t.cv_filechecksums";
+  EmitEOL();
+}
+
 void MCAsmStreamer::EmitIdent(StringRef IdentString) {
   assert(MAI->hasIdentDirective() && ".ident directive not supported");
   OS << "\t.ident\t";

Added: llvm/trunk/lib/MC/MCCodeView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCCodeView.cpp?rev=259130&view=auto
==============================================================================
--- llvm/trunk/lib/MC/MCCodeView.cpp (added)
+++ llvm/trunk/lib/MC/MCCodeView.cpp Thu Jan 28 18:49:42 2016
@@ -0,0 +1,222 @@
+//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Holds state from .cv_file and .cv_loc directives for later emission.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCCodeView.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/Support/COFF.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+CodeViewContext::CodeViewContext() {}
+
+CodeViewContext::~CodeViewContext() {
+  // If someone inserted strings into the string table but never actually
+  // emitted them somewhere, clean up the fragment.
+  if (!InsertedStrTabFragment)
+    delete StrTabFragment;
+}
+
+/// This is a valid number for use with .cv_loc if we've already seen a .cv_file
+/// for it.
+bool CodeViewContext::isValidFileNumber(unsigned FileNumber) const {
+  unsigned Idx = FileNumber - 1;
+  if (Idx < Filenames.size())
+    return !Filenames[Idx].empty();
+  return false;
+}
+
+bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
+  assert(FileNumber > 0);
+  Filename = addToStringTable(Filename);
+  unsigned Idx = FileNumber - 1;
+  if (Idx >= Filenames.size())
+    Filenames.resize(Idx + 1);
+
+  if (Filename.empty())
+    Filename = "<stdin>";
+
+  if (!Filenames[Idx].empty())
+    return false;
+
+  // FIXME: We should store the string table offset of the filename, rather than
+  // the filename itself for efficiency.
+  Filename = addToStringTable(Filename);
+
+  Filenames[Idx] = Filename;
+  return true;
+}
+
+MCDataFragment *CodeViewContext::getStringTableFragment() {
+  if (!StrTabFragment) {
+    StrTabFragment = new MCDataFragment();
+    // Start a new string table out with a null byte.
+    StrTabFragment->getContents().push_back('\0');
+  }
+  return StrTabFragment;
+}
+
+StringRef CodeViewContext::addToStringTable(StringRef S) {
+  SmallVectorImpl<char> &Contents = getStringTableFragment()->getContents();
+  auto Insertion =
+      StringTable.insert(std::make_pair(S, unsigned(Contents.size())));
+  // Return the string from the table, since it is stable.
+  S = Insertion.first->first();
+  if (Insertion.second) {
+    // The string map key is always null terminated.
+    Contents.append(S.begin(), S.end() + 1);
+  }
+  return S;
+}
+
+unsigned CodeViewContext::getStringTableOffset(StringRef S) {
+  // A string table offset of zero is always the empty string.
+  if (S.empty())
+    return 0;
+  auto I = StringTable.find(S);
+  assert(I != StringTable.end());
+  return I->second;
+}
+
+void CodeViewContext::emitStringTable(MCObjectStreamer &OS) {
+  MCContext &Ctx = OS.getContext();
+  MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin"),
+           *StringEnd = Ctx.createTempSymbol("strtab_end");
+
+  OS.EmitIntValue(unsigned(ModuleSubstreamKind::StringTable), 4);
+  OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4);
+  OS.EmitLabel(StringBegin);
+
+  // Put the string table data fragment here, if we haven't already put it
+  // somewhere else. If somebody wants two string tables in their .s file, one
+  // will just be empty.
+  if (!InsertedStrTabFragment) {
+    OS.insert(getStringTableFragment());
+    InsertedStrTabFragment = true;
+  }
+
+  OS.EmitValueToAlignment(4, 0);
+
+  OS.EmitLabel(StringEnd);
+}
+
+void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) {
+  MCContext &Ctx = OS.getContext();
+  MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin"),
+           *FileEnd = Ctx.createTempSymbol("filechecksums_end");
+
+  OS.EmitIntValue(unsigned(ModuleSubstreamKind::FileChecksums), 4);
+  OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4);
+  OS.EmitLabel(FileBegin);
+
+  // Emit an array of FileChecksum entries. We index into this table using the
+  // user-provided file number. Each entry is currently 8 bytes, as we don't
+  // emit checksums.
+  for (StringRef Filename : Filenames) {
+    OS.EmitIntValue(getStringTableOffset(Filename), 4);
+    // Zero the next two fields and align back to 4 bytes. This indicates that
+    // no checksum is present.
+    OS.EmitIntValue(0, 4);
+  }
+
+  OS.EmitLabel(FileEnd);
+}
+
+void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
+                                               unsigned FuncId,
+                                               const MCSymbol *FuncBegin,
+                                               const MCSymbol *FuncEnd) {
+  MCContext &Ctx = OS.getContext();
+  MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin"),
+           *LineEnd = Ctx.createTempSymbol("linetable_end");
+
+  OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4);
+  OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
+  OS.EmitLabel(LineBegin);
+  OS.EmitCOFFSecRel32(FuncBegin);
+  OS.EmitCOFFSectionIndex(FuncBegin);
+
+  // Actual line info.
+  ArrayRef<MCCVLineEntry> Locs = getFunctionLineEntries(FuncId);
+  bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) {
+    return LineEntry.getColumn() != 0;
+  });
+  OS.EmitIntValue(HaveColumns ? int(codeview::LineFlags::HaveColumns) : 0, 2);
+  OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4);
+
+  for (auto I = Locs.begin(), E = Locs.end(); I != E;) {
+    // Emit a file segment for the run of locations that share a file id.
+    unsigned CurFileNum = I->getFileNum();
+    auto FileSegEnd =
+        std::find_if(I, E, [CurFileNum](const MCCVLineEntry &Loc) {
+          return Loc.getFileNum() != CurFileNum;
+        });
+    unsigned EntryCount = FileSegEnd - I;
+    OS.AddComment("Segment for file '" + Twine(Filenames[CurFileNum - 1]) +
+                  "' begins");
+    OS.EmitIntValue(8 * (CurFileNum - 1), 4);
+    OS.EmitIntValue(EntryCount, 4);
+    uint32_t SegmentSize = 12;
+    SegmentSize += 8 * EntryCount;
+    if (HaveColumns)
+      SegmentSize += 4 * EntryCount;
+    OS.EmitIntValue(SegmentSize, 4);
+
+    for (auto J = I; J != FileSegEnd; ++J) {
+      OS.emitAbsoluteSymbolDiff(J->getLabel(), FuncBegin, 4);
+      unsigned LineData = J->getLine();
+      if (J->isStmt())
+        LineData |= codeview::LineInfo::StatementFlag;
+      OS.EmitIntValue(LineData, 4);
+    }
+    if (HaveColumns) {
+      for (auto J = I; J != FileSegEnd; ++J) {
+        OS.EmitIntValue(J->getColumn(), 2);
+        OS.EmitIntValue(0, 2);
+      }
+    }
+    I = FileSegEnd;
+  }
+  OS.EmitLabel(LineEnd);
+}
+
+//
+// This is called when an instruction is assembled into the specified section
+// and if there is information from the last .cv_loc directive that has yet to have
+// a line entry made for it is made.
+//
+void MCCVLineEntry::Make(MCObjectStreamer *MCOS) {
+  if (!MCOS->getContext().getCVLocSeen())
+    return;
+
+  // Create a symbol at in the current section for use in the line entry.
+  MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
+  // Set the value of the symbol to use for the MCCVLineEntry.
+  MCOS->EmitLabel(LineSym);
+
+  // Get the current .loc info saved in the context.
+  const MCCVLoc &CVLoc = MCOS->getContext().getCurrentCVLoc();
+
+  // Create a (local) line entry with the symbol and the current .loc info.
+  MCCVLineEntry LineEntry(LineSym, CVLoc);
+
+  // clear CVLocSeen saying the current .loc info is now used.
+  MCOS->getContext().clearCVLocSeen();
+
+  // Add the line entry to this section's entries.
+  MCOS->getContext().getCVContext().addLineEntry(LineEntry);
+}

Modified: llvm/trunk/lib/MC/MCContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCContext.cpp (original)
+++ llvm/trunk/lib/MC/MCContext.cpp Thu Jan 28 18:49:42 2016
@@ -12,6 +12,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeView.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCLabel.h"
 #include "llvm/MC/MCObjectFileInfo.h"
@@ -90,6 +91,8 @@ void MCContext::reset() {
   DwarfCompileUnitID = 0;
   CurrentDwarfLoc = MCDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0);
 
+  CVContext.reset();
+
   MachOUniquingMap.clear();
   ELFUniquingMap.clear();
   COFFUniquingMap.clear();
@@ -474,6 +477,20 @@ void MCContext::finalizeDwarfSections(MC
       [&](MCSection *Sec) { return !MCOS.mayHaveInstructions(*Sec); });
 }
 
+CodeViewContext &MCContext::getCVContext() {
+  if (!CVContext.get())
+    CVContext.reset(new CodeViewContext);
+  return *CVContext.get();
+}
+
+unsigned MCContext::getCVFile(StringRef FileName, unsigned FileNumber) {
+  return getCVContext().addFile(FileNumber, FileName) ? FileNumber : 0;
+}
+
+bool MCContext::isValidCVFileNumber(unsigned FileNumber) {
+  return getCVContext().isValidFileNumber(FileNumber);
+}
+
 //===----------------------------------------------------------------------===//
 // Error Reporting
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Thu Jan 28 18:49:42 2016
@@ -125,6 +125,7 @@ void MCObjectStreamer::EmitValueImpl(con
   MCDataFragment *DF = getOrCreateDataFragment();
   flushPendingLabels(DF, DF->getContents().size());
 
+  MCCVLineEntry::Make(this);
   MCDwarfLineEntry::Make(this, getCurrentSection().first);
 
   // Avoid fixups when possible.
@@ -232,6 +233,7 @@ void MCObjectStreamer::EmitInstruction(c
 
   // Now that a machine instruction has been assembled into this section, make
   // a line entry for any .loc directive that has been seen.
+  MCCVLineEntry::Make(this);
   MCDwarfLineEntry::Make(this, getCurrentSection().first);
 
   // If this instruction doesn't need relaxation, just emit it as data.
@@ -362,7 +364,36 @@ void MCObjectStreamer::EmitDwarfAdvanceF
   insert(new MCDwarfCallFrameFragment(*AddrDelta));
 }
 
+void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+                                          unsigned Line, unsigned Column,
+                                          bool PrologueEnd, bool IsStmt,
+                                          StringRef FileName) {
+  // In case we see two .cv_loc directives in a row, make sure the
+  // first one gets a line entry.
+  MCCVLineEntry::Make(this);
+
+  this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
+                                       PrologueEnd, IsStmt, FileName);
+}
+
+void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+                                                const MCSymbol *Begin,
+                                                const MCSymbol *End) {
+  getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
+                                                       End);
+  this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End);
+}
+
+void MCObjectStreamer::EmitCVStringTableDirective() {
+  getContext().getCVContext().emitStringTable(*this);
+}
+void MCObjectStreamer::EmitCVFileChecksumsDirective() {
+  getContext().getCVContext().emitFileChecksums(*this);
+}
+
+
 void MCObjectStreamer::EmitBytes(StringRef Data) {
+  MCCVLineEntry::Make(this);
   MCDwarfLineEntry::Make(this, getCurrentSection().first);
   MCDataFragment *DF = getOrCreateDataFragment();
   flushPendingLabels(DF, DF->getContents().size());

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Thu Jan 28 18:49:42 2016
@@ -357,6 +357,8 @@ private:
     DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFNES, DK_IFDEF, DK_IFNDEF,
     DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF,
     DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS,
+    DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_STRINGTABLE,
+    DK_CV_FILECHECKSUMS,
     DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA,
     DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER,
     DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA,
@@ -394,6 +396,13 @@ private:
   bool parseDirectiveLoc();
   bool parseDirectiveStabs();
 
+  // ".cv_file", ".cv_loc", ".cv_linetable"
+  bool parseDirectiveCVFile();
+  bool parseDirectiveCVLoc();
+  bool parseDirectiveCVLinetable();
+  bool parseDirectiveCVStringTable();
+  bool parseDirectiveCVFileChecksums();
+
   // .cfi directives
   bool parseDirectiveCFIRegister(SMLoc DirectiveLoc);
   bool parseDirectiveCFIWindowSave();
@@ -1638,6 +1647,16 @@ bool AsmParser::parseStatement(ParseStat
       return parseDirectiveLoc();
     case DK_STABS:
       return parseDirectiveStabs();
+    case DK_CV_FILE:
+      return parseDirectiveCVFile();
+    case DK_CV_LOC:
+      return parseDirectiveCVLoc();
+    case DK_CV_LINETABLE:
+      return parseDirectiveCVLinetable();
+    case DK_CV_STRINGTABLE:
+      return parseDirectiveCVStringTable();
+    case DK_CV_FILECHECKSUMS:
+      return parseDirectiveCVFileChecksums();
     case DK_CFI_SECTIONS:
       return parseDirectiveCFISections();
     case DK_CFI_STARTPROC:
@@ -3070,6 +3089,156 @@ bool AsmParser::parseDirectiveStabs() {
   return TokError("unsupported directive '.stabs'");
 }
 
+/// parseDirectiveCVFile
+/// ::= .cv_file number filename
+bool AsmParser::parseDirectiveCVFile() {
+  SMLoc FileNumberLoc = getLexer().getLoc();
+  if (getLexer().isNot(AsmToken::Integer))
+    return TokError("expected file number in '.cv_file' directive");
+
+  int64_t FileNumber = getTok().getIntVal();
+  Lex();
+
+  if (FileNumber < 1)
+    return TokError("file number less than one");
+
+  if (getLexer().isNot(AsmToken::String))
+    return TokError("unexpected token in '.cv_file' directive");
+
+  // Usually the directory and filename together, otherwise just the directory.
+  // Allow the strings to have escaped octal character sequence.
+  std::string Filename;
+  if (parseEscapedString(Filename))
+    return true;
+  Lex();
+
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return TokError("unexpected token in '.cv_file' directive");
+
+  if (getStreamer().EmitCVFileDirective(FileNumber, Filename) == 0)
+    Error(FileNumberLoc, "file number already allocated");
+
+  return false;
+}
+
+/// parseDirectiveCVLoc
+/// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
+///                                [is_stmt VALUE]
+/// The first number is a file number, must have been previously assigned with
+/// a .file directive, the second number is the line number and optionally the
+/// third number is a column position (zero if not specified).  The remaining
+/// optional items are .loc sub-directives.
+bool AsmParser::parseDirectiveCVLoc() {
+  if (getLexer().isNot(AsmToken::Integer))
+    return TokError("unexpected token in '.cv_loc' directive");
+
+  int64_t FunctionId = getTok().getIntVal();
+  if (FunctionId < 0)
+    return TokError("function id less than zero in '.cv_loc' directive");
+  Lex();
+
+  int64_t FileNumber = getTok().getIntVal();
+  if (FileNumber < 1)
+    return TokError("file number less than one in '.cv_loc' directive");
+  if (!getContext().isValidCVFileNumber(FileNumber))
+    return TokError("unassigned file number in '.cv_loc' directive");
+  Lex();
+
+  int64_t LineNumber = 0;
+  if (getLexer().is(AsmToken::Integer)) {
+    LineNumber = getTok().getIntVal();
+    if (LineNumber < 0)
+      return TokError("line number less than zero in '.cv_loc' directive");
+    Lex();
+  }
+
+  int64_t ColumnPos = 0;
+  if (getLexer().is(AsmToken::Integer)) {
+    ColumnPos = getTok().getIntVal();
+    if (ColumnPos < 0)
+      return TokError("column position less than zero in '.cv_loc' directive");
+    Lex();
+  }
+
+  bool PrologueEnd = false;
+  uint64_t IsStmt = 0;
+  while (getLexer().isNot(AsmToken::EndOfStatement)) {
+    StringRef Name;
+    SMLoc Loc = getTok().getLoc();
+    if (parseIdentifier(Name))
+      return TokError("unexpected token in '.cv_loc' directive");
+
+    if (Name == "prologue_end")
+      PrologueEnd = true;
+    else if (Name == "is_stmt") {
+      Loc = getTok().getLoc();
+      const MCExpr *Value;
+      if (parseExpression(Value))
+        return true;
+      // The expression must be the constant 0 or 1.
+      IsStmt = ~0ULL;
+      if (const auto *MCE = dyn_cast<MCConstantExpr>(Value))
+        IsStmt = MCE->getValue();
+
+      if (IsStmt > 1)
+        return Error(Loc, "is_stmt value not 0 or 1");
+    } else {
+      return Error(Loc, "unknown sub-directive in '.cv_loc' directive");
+    }
+  }
+
+  getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
+                                   ColumnPos, PrologueEnd, IsStmt, StringRef());
+  return false;
+}
+
+/// parseDirectiveCVLinetable
+/// ::= .cv_linetable FunctionId, FnStart, FnEnd
+bool AsmParser::parseDirectiveCVLinetable() {
+  int64_t FunctionId = getTok().getIntVal();
+  if (FunctionId < 0)
+    return TokError("function id less than zero in '.cv_linetable' directive");
+  Lex();
+
+  if (Lexer.isNot(AsmToken::Comma))
+    return TokError("unexpected token in '.cv_linetable' directive");
+  Lex();
+
+  SMLoc Loc = getLexer().getLoc();
+  StringRef FnStartName;
+  if (parseIdentifier(FnStartName))
+    return Error(Loc, "expected identifier in directive");
+
+  if (Lexer.isNot(AsmToken::Comma))
+    return TokError("unexpected token in '.cv_linetable' directive");
+  Lex();
+
+  Loc = getLexer().getLoc();
+  StringRef FnEndName;
+  if (parseIdentifier(FnEndName))
+    return Error(Loc, "expected identifier in directive");
+
+  MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
+  MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
+
+  getStreamer().EmitCVLinetableDirective(FunctionId, FnStartSym, FnEndSym);
+  return false;
+}
+
+/// parseDirectiveCVStringTable
+/// ::= .cv_stringtable
+bool AsmParser::parseDirectiveCVStringTable() {
+  getStreamer().EmitCVStringTableDirective();
+  return false;
+}
+
+/// parseDirectiveCVFileChecksums
+/// ::= .cv_filechecksums
+bool AsmParser::parseDirectiveCVFileChecksums() {
+  getStreamer().EmitCVFileChecksumsDirective();
+  return false;
+}
+
 /// parseDirectiveCFISections
 /// ::= .cfi_sections section [, section]
 bool AsmParser::parseDirectiveCFISections() {
@@ -4381,6 +4550,11 @@ void AsmParser::initializeDirectiveKindM
   DirectiveKindMap[".line"] = DK_LINE;
   DirectiveKindMap[".loc"] = DK_LOC;
   DirectiveKindMap[".stabs"] = DK_STABS;
+  DirectiveKindMap[".cv_file"] = DK_CV_FILE;
+  DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
+  DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
+  DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
+  DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
   DirectiveKindMap[".sleb128"] = DK_SLEB128;
   DirectiveKindMap[".uleb128"] = DK_ULEB128;
   DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;

Modified: llvm/trunk/lib/MC/MCStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCStreamer.cpp Thu Jan 28 18:49:42 2016
@@ -180,6 +180,22 @@ void MCStreamer::EnsureValidDwarfFrame()
     report_fatal_error("No open frame");
 }
 
+unsigned MCStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
+  return getContext().getCVFile(Filename, FileNo);
+}
+
+void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
+                                    unsigned Line, unsigned Column,
+                                    bool PrologueEnd, bool IsStmt,
+                                    StringRef FileName) {
+  getContext().setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd,
+                               IsStmt);
+}
+
+void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
+                                          const MCSymbol *Begin,
+                                          const MCSymbol *End) {}
+
 void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
                                      MCSymbol *EHSymbol) {
 }

Modified: llvm/trunk/lib/MC/StringTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/StringTableBuilder.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/lib/MC/StringTableBuilder.cpp (original)
+++ llvm/trunk/lib/MC/StringTableBuilder.cpp Thu Jan 28 18:49:42 2016
@@ -16,7 +16,22 @@
 
 using namespace llvm;
 
-StringTableBuilder::StringTableBuilder(Kind K) : K(K) {}
+StringTableBuilder::StringTableBuilder(Kind K) : K(K) {
+  // Account for leading bytes in table so that offsets returned from add are
+  // correct.
+  switch (K) {
+  case RAW:
+    Size = 0;
+    break;
+  case MachO:
+  case ELF:
+    Size = 1;
+    break;
+  case WinCOFF:
+    Size = 4;
+    break;
+  }
+}
 
 typedef std::pair<StringRef, size_t> StringPair;
 
@@ -62,13 +77,32 @@ tailcall:
 }
 
 void StringTableBuilder::finalize() {
-  std::vector<std::pair<StringRef, size_t> *> Strings;
+  finalizeStringTable(/*Optimize=*/true);
+}
+
+void StringTableBuilder::finalizeInOrder() {
+  finalizeStringTable(/*Optimize=*/false);
+}
+
+void StringTableBuilder::finalizeStringTable(bool Optimize) {
+  typedef std::pair<StringRef, size_t> StringOffsetPair;
+  std::vector<StringOffsetPair *> Strings;
   Strings.reserve(StringIndexMap.size());
-  for (std::pair<StringRef, size_t> &P : StringIndexMap)
+  for (StringOffsetPair &P : StringIndexMap)
     Strings.push_back(&P);
 
-  if (!Strings.empty())
-    multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
+  if (!Strings.empty()) {
+    // If we're optimizing, sort by name. If not, sort by previously assigned
+    // offset.
+    if (Optimize) {
+      multikey_qsort(&Strings[0], &Strings[0] + Strings.size(), 0);
+    } else {
+      std::sort(Strings.begin(), Strings.end(),
+                [](const StringOffsetPair *LHS, const StringOffsetPair *RHS) {
+                  return LHS->second < RHS->second;
+                });
+    }
+  }
 
   switch (K) {
   case RAW:
@@ -85,17 +119,22 @@ void StringTableBuilder::finalize() {
   }
 
   StringRef Previous;
-  for (std::pair<StringRef, size_t> *P : Strings) {
+  for (StringOffsetPair *P : Strings) {
     StringRef S = P->first;
     if (K == WinCOFF)
       assert(S.size() > COFF::NameSize && "Short string in COFF string table!");
 
-    if (Previous.endswith(S)) {
+    if (Optimize && Previous.endswith(S)) {
       P->second = StringTable.size() - S.size() - (K != RAW);
       continue;
     }
 
-    P->second = StringTable.size();
+    if (Optimize)
+      P->second = StringTable.size();
+    else
+      assert(P->second == StringTable.size() &&
+             "different strtab offset after finalization");
+
     StringTable += S;
     if (K != RAW)
       StringTable += '\x00';

Modified: llvm/trunk/test/DebugInfo/COFF/asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/asm.ll?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/asm.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/asm.ll Thu Jan 28 18:49:42 2016
@@ -13,11 +13,11 @@
 ;  6 }
 
 ; X86-LABEL: _f:
-; X86:      # BB
-; X86-NEXT: [[ASM_LINE:^L.*]]:{{$}}
-; X86:      [[CALL_LINE:^L.*]]:{{$}}
+; X86:      .cv_file 1 "D:\\asm.c"
+; X86:      .cv_loc 0 1 4 0 is_stmt 0
+; X86:      .cv_loc 0 1 5 0
 ; X86:      calll   _g
-; X86-NEXT: [[RETURN_STMT:.*]]:
+; X86:      .cv_loc 0 1 6 0
 ; X86:      ret
 ; X86-NEXT: [[END_OF_F:^L.*]]:
 ;
@@ -45,48 +45,15 @@
 ; Padding
 ; X86-NEXT: .zero   3
 ; Line table
-; X86-NEXT: .long   242
-; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X86-NEXT: [[F2_START]]:
-; X86-NEXT: .secrel32 _f
-; X86-NEXT: .secidx _f
-; X86-NEXT: .short 1
-; X86-NEXT: .long [[END_OF_F]]-_f
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   3
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[ASM_LINE]]-_f
-; X86-NEXT: .long   -2147483644
-; X86-NEXT: .long [[CALL_LINE]]-_f
-; X86-NEXT: .long   -2147483643
-; X86-NEXT: .long [[RETURN_STMT]]-_f
-; X86-NEXT: .long   -2147483642
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; X86-NEXT: [[F2_END]]:
+; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
 ; File index to string table offset subsection
-; X86-NEXT: .long   244
-; X86-NEXT: .long   8
-; X86-NEXT: .long   1
-; X86-NEXT: .long   0
+; X86-NEXT: .cv_filechecksums
 ; String table
-; X86-NEXT: .long   243
-; X86-NEXT: .long   10
-; X86-NEXT: .byte   0
-; X86-NEXT: .ascii  "D:\\asm.c"
-; X86-NEXT: .byte   0
-; Padding
-; X86-NEXT: .zero   2
+; X86-NEXT: .cv_stringtable
 
 ; OBJ32:    Section {
 ; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      Characteristics [ (0x42300040)
 ; OBJ32:      ]
 ; OBJ32:      Relocations [
 ; OBJ32-NEXT:   0x2C IMAGE_REL_I386_SECREL _f
@@ -107,7 +74,7 @@
 ; OBJ32-NEXT: ]
 ; OBJ32:      FunctionLineTable [
 ; OBJ32-NEXT:   Name: _f
-; OBJ32-NEXT:   Flags: 0x1
+; OBJ32-NEXT:   Flags: 0x0
 ; OBJ32-NEXT:   CodeSize: 0x6
 ; OBJ32-NEXT:   FilenameSegment [
 ; OBJ32-NEXT:   Filename: D:\asm.c
@@ -118,34 +85,27 @@
 ; OBJ32-NEXT:     LineNumberStart: 4
 ; OBJ32-NEXT:     LineNumberEndDelta: 0
 ; OBJ32-NEXT:     IsStatement: Yes
-; OBJ32-NEXT:     ColStart: 0
-; OBJ32-NEXT:     ColEnd: 0
 ; OBJ32-NEXT:   ]
 ; OBJ32-NEXT:   +0x0 [
 ; OBJ32-NEXT:     LineNumberStart: 5
 ; OBJ32-NEXT:     LineNumberEndDelta: 0
 ; OBJ32-NEXT:     IsStatement: Yes
-; OBJ32-NEXT:     ColStart: 0
-; OBJ32-NEXT:     ColEnd: 0
 ; OBJ32-NEXT:   ]
 ; OBJ32-NEXT:   +0x5 [
 ; OBJ32-NEXT:     LineNumberStart: 6
 ; OBJ32-NEXT:     LineNumberEndDelta: 0
 ; OBJ32-NEXT:     IsStatement: Yes
-; OBJ32-NEXT:     ColStart: 0
-; OBJ32-NEXT:     ColEnd: 0
 ; OBJ32-NEXT:   ]
 ; OBJ32-NEXT: ]
 
 ; X64-LABEL: f:
-; X64-NEXT: .L{{.*}}:{{$}}
-; X64-NEXT: [[START:.*]]:{{$}}
-; X64:      # BB
+; X64:      .cv_file 1 "D:\\asm.c"
+; X64:      .cv_loc 0 1 3 0 is_stmt 0
 ; X64:      subq    $40, %rsp
-; X64-NEXT: [[ASM_LINE:.*]]:{{$}}
-; X64:      [[CALL_LINE:.*]]:{{$}}
+; X64:      .cv_loc 0 1 4 0
+; X64:      .cv_loc 0 1 5 0
 ; X64:      callq   g
-; X64-NEXT: [[EPILOG_AND_RET:.*]]:
+; X64:      .cv_loc 0 1 6 0
 ; X64:      addq    $40, %rsp
 ; X64-NEXT: ret
 ; X64-NEXT: [[END_OF_F:.*]]:
@@ -174,52 +134,15 @@
 ; Padding
 ; X64-NEXT: .zero   3
 ; Line table
-; X64-NEXT: .long   242
-; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X64-NEXT: [[F2_START]]:
-; X64-NEXT: .secrel32 f
-; X64-NEXT: .secidx f
-; X64-NEXT: .short 1
-; X64-NEXT: .long [[END_OF_F]]-f
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   0
-; X64-NEXT: .long   4
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[START]]-f
-; X64-NEXT: .long   -2147483645
-; X64-NEXT: .long [[ASM_LINE]]-f
-; X64-NEXT: .long   -2147483644
-; X64-NEXT: .long [[CALL_LINE]]-f
-; X64-NEXT: .long   -2147483643
-; X64-NEXT: .long [[EPILOG_AND_RET]]-f
-; X64-NEXT: .long   -2147483642
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; X64-NEXT: [[F2_END]]:
+; X64-NEXT: .cv_linetable 0, f, [[END_OF_F]]
 ; File index to string table offset subsection
-; X64-NEXT: .long   244
-; X64-NEXT: .long   8
-; X64-NEXT: .long   1
-; X64-NEXT: .long   0
+; X64-NEXT: .cv_filechecksums
 ; String table
-; X64-NEXT: .long   243
-; X64-NEXT: .long   10
-; X64-NEXT: .byte   0
-; X64-NEXT: .ascii  "D:\\asm.c"
-; X64-NEXT: .byte   0
-; Padding
-; X64-NEXT: .zero   2
+; X64-NEXT: .cv_stringtable
 
 ; OBJ64:    Section {
 ; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      Characteristics [ (0x42300040)
 ; OBJ64:      ]
 ; OBJ64:      Relocations [
 ; OBJ64-NEXT:   0x2C IMAGE_REL_AMD64_SECREL f
@@ -239,7 +162,7 @@
 ; OBJ64-NEXT: ]
 ; OBJ64:      FunctionLineTable [
 ; OBJ64-NEXT:   Name: f
-; OBJ64-NEXT:   Flags: 0x1
+; OBJ64-NEXT:   Flags: 0x0
 ; OBJ64-NEXT:   CodeSize: 0xE
 ; OBJ64-NEXT:   FilenameSegment [
 ; OBJ64-NEXT:     Filename: D:\asm.c
@@ -249,29 +172,21 @@
 ; OBJ64-NEXT:       LineNumberStart: 3
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:     +0x4 [
 ; OBJ64-NEXT:       LineNumberStart: 4
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:     +0x4 [
 ; OBJ64-NEXT:       LineNumberStart: 5
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:     +0x9 [
 ; OBJ64-NEXT:       LineNumberStart: 6
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:   ]
 ; OBJ64-NEXT: ]

Modified: llvm/trunk/test/DebugInfo/COFF/multifile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifile.ll?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/multifile.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/multifile.ll Thu Jan 28 18:49:42 2016
@@ -18,13 +18,15 @@
 
 ; X86-LABEL: _f:
 ; X86:      # BB
-; X86-NEXT: [[CALL_LINE_1:.*]]:{{$}}
+; X86:      .cv_file 1 "D:\\one.c"
+; X86:      .cv_loc 0 1 1 0 is_stmt 0 # one.c:1:0
 ; X86:      calll   _g
-; X86-NEXT: [[CALL_LINE_2:.*]]:{{$}}
+; X86:      .cv_file 2 "D:\\two.c"
+; X86:      .cv_loc 0 2 2 0 # two.c:2:0
 ; X86:      calll   _g
-; X86-NEXT: [[CALL_LINE_3:.*]]:{{$}}
+; X86:      .cv_loc 0 1 7 0 # one.c:7:0
 ; X86:      calll   _g
-; X86-NEXT: [[RETURN_STMT:.*]]:
+; X86:      .cv_loc 0 1 8 0 # one.c:8:0
 ; X86:      ret
 ; X86-NEXT: [[END_OF_F:.*]]:
 ;
@@ -52,68 +54,15 @@
 ; Padding
 ; X86-NEXT: .zero   3
 ; Line table
-; X86-NEXT: .long   242
-; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X86-NEXT: [[F2_START]]:
-; X86-NEXT: .secrel32 _f
-; X86-NEXT: .secidx _f
-; X86-NEXT: .short 1
-; X86-NEXT: .long [[END_OF_F]]-_f
-; Segment for file 'D:\\one.c' begins
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   1
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[CALL_LINE_1]]-_f
-; X86-NEXT: .long   -2147483647
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; Segment for file 'D:\\two.c' begins
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   8
-; X86-NEXT: .long   1
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[CALL_LINE_2]]-_f
-; X86-NEXT: .long   -2147483646
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; A new segment for file 'D:\\one.c' begins
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   2
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[CALL_LINE_3]]-_f
-; X86-NEXT: .long   -2147483641
-; X86-NEXT: .long [[RETURN_STMT]]-_f
-; X86-NEXT: .long   -2147483640
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; X86-NEXT: [[F2_END]]:
+; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
 ; File index to string table offset subsection
-; X86-NEXT: .long   244
-; X86-NEXT: .long   16
-; X86-NEXT: .long   1
-; X86-NEXT: .long   0
-; X86-NEXT: .long   10
-; X86-NEXT: .long   0
+; X86-NEXT: .cv_filechecksums
 ; String table
-; X86-NEXT: .long   243
-; X86-NEXT: .long   19
-; X86-NEXT: .byte   0
-; X86-NEXT: .ascii  "D:\\one.c"
-; X86-NEXT: .byte   0
-; X86-NEXT: .ascii  "D:\\two.c"
-; X86-NEXT: .byte   0
-; X86-NEXT: .zero   1
+; X86-NEXT: .cv_stringtable
 
 ; OBJ32:    Section {
 ; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      Characteristics [ (0x42300040)
 ; OBJ32:      ]
 ; OBJ32:      Relocations [
 ; OBJ32-NEXT:   0x2C IMAGE_REL_I386_SECREL _f
@@ -133,7 +82,7 @@
 ; OBJ32-NEXT: ]
 ; OBJ32:      FunctionLineTable [
 ; OBJ32-NEXT:   Name: _f
-; OBJ32-NEXT:   Flags: 0x1
+; OBJ32-NEXT:   Flags: 0x0
 ; OBJ32-NEXT:   CodeSize: 0x10
 ; OBJ32-NEXT:   FilenameSegment [
 ; OBJ32-NEXT:     Filename: D:\one.c
@@ -141,8 +90,6 @@
 ; OBJ32-NEXT:       LineNumberStart: 1
 ; OBJ32-NEXT:       LineNumberEndDelta: 0
 ; OBJ32-NEXT:       IsStatement: Yes
-; OBJ32-NEXT:       ColStart: 0
-; OBJ32-NEXT:       ColEnd: 0
 ; OBJ32-NEXT:     ]
 ; OBJ32-NEXT:   ]
 ; OBJ32-NEXT:   FilenameSegment [
@@ -151,8 +98,6 @@
 ; OBJ32-NEXT:       LineNumberStart: 2
 ; OBJ32-NEXT:       LineNumberEndDelta: 0
 ; OBJ32-NEXT:       IsStatement: Yes
-; OBJ32-NEXT:       ColStart: 0
-; OBJ32-NEXT:       ColEnd: 0
 ; OBJ32-NEXT:     ]
 ; OBJ32-NEXT:   ]
 ; OBJ32-NEXT:   FilenameSegment [
@@ -161,31 +106,30 @@
 ; OBJ32-NEXT:       LineNumberStart: 7
 ; OBJ32-NEXT:       LineNumberEndDelta: 0
 ; OBJ32-NEXT:       IsStatement: Yes
-; OBJ32-NEXT:       ColStart: 0
-; OBJ32-NEXT:       ColEnd: 0
 ; OBJ32-NEXT:     ]
 ; OBJ32-NEXT:     +0xF [
 ; OBJ32-NEXT:       LineNumberStart: 8
 ; OBJ32-NEXT:       LineNumberEndDelta: 0
 ; OBJ32-NEXT:       IsStatement: Yes
-; OBJ32-NEXT:       ColStart: 0
-; OBJ32-NEXT:       ColEnd: 0
 ; OBJ32-NEXT:     ]
 ; OBJ32-NEXT:   ]
 ; OBJ32-NEXT: ]
 
 ; X64-LABEL: f:
 ; X64-NEXT: .L{{.*}}:{{$}}
-; X64-NEXT: [[START:.*]]:{{$}}
+; X64:      .cv_file 1 "D:\\input.c"
+; X64:      .cv_loc 0 1 3 0 is_stmt 0 # input.c:3:0
 ; X64:      # BB
 ; X64:      subq    $40, %rsp
-; X64-NEXT: [[CALL_LINE_1:.*]]:{{$}}
+; X64:      .cv_file 2 "D:\\one.c"
+; X64:      .cv_loc 0 2 1 0 # one.c:1:0
 ; X64:      callq   g
-; X64-NEXT: [[CALL_LINE_2:.*]]:{{$}}
+; X64:      .cv_file 3 "D:\\two.c"
+; X64:      .cv_loc 0 3 2 0 # two.c:2:0
 ; X64:      callq   g
-; X64-NEXT: [[CALL_LINE_3:.*]]:{{$}}
+; X64:      .cv_loc 0 2 7 0 # one.c:7:0
 ; X64:      callq   g
-; X64-NEXT: [[EPILOG_AND_RET:.*]]:
+; X64:      .cv_loc 0 2 8 0 # one.c:8:0
 ; X64:      addq    $40, %rsp
 ; X64-NEXT: ret
 ; X64-NEXT: [[END_OF_F:.*]]:
@@ -213,83 +157,13 @@
 ; X64-NEXT: [[F1_END]]:
 ; Padding
 ; X64-NEXT: .zero   3
-; Line table
-; X64-NEXT: .long   242
-; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X64-NEXT: [[F2_START]]:
-; X64-NEXT: .secrel32 f
-; X64-NEXT: .secidx f
-; X64-NEXT: .short 1
-; X64-NEXT: .long [[END_OF_F]]-f
-; Segment for file 'D:\\input.c' begins
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   0
-; X64-NEXT: .long   1
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[START]]-f
-; X64-NEXT: .long   -2147483645
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; Segment for file 'D:\\one.c' begins
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   8
-; X64-NEXT: .long   1
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[CALL_LINE_1]]-f
-; X64-NEXT: .long   -2147483647
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; Segment for file 'D:\\two.c' begins
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   16
-; X64-NEXT: .long   1
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[CALL_LINE_2]]-f
-; X64-NEXT: .long   -2147483646
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; A new segment for file 'D:\\one.c' begins
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   8
-; X64-NEXT: .long   2
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[CALL_LINE_3]]-f
-; X64-NEXT: .long   -2147483641
-; X64-NEXT: .long [[EPILOG_AND_RET]]-f
-; X64-NEXT: .long   -2147483640
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; X64-NEXT: [[F2_END]]:
-; File index to string table offset subsection
-; X64-NEXT: .long   244
-; X64-NEXT: .long   24
-; X64-NEXT: .long   1
-; X64-NEXT: .long   0
-; X64-NEXT: .long   12
-; X64-NEXT: .long   0
-; X64-NEXT: .long   21
-; X64-NEXT: .long   0
-; String table
-; X64-NEXT: .long   243
-; X64-NEXT: .long   30
-; X64-NEXT: .byte   0
-; X64-NEXT: .ascii  "D:\\input.c"
-; X64-NEXT: .byte   0
-; X64-NEXT: .ascii  "D:\\one.c"
-; X64-NEXT: .byte   0
-; X64-NEXT: .ascii  "D:\\two.c"
-; X64-NEXT: .byte   0
-; X64-NEXT: .zero   2
+; X64: .cv_linetable 0, f, [[END_OF_F]]
+; X64: .cv_filechecksums
+; X64: .cv_stringtable
 
 ; OBJ64:    Section {
 ; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      Characteristics [ (0x42300040)
 ; OBJ64:      ]
 ; OBJ64:      Relocations [
 ; OBJ64-NEXT:   0x2C IMAGE_REL_AMD64_SECREL f
@@ -309,7 +183,7 @@
 ; OBJ64-NEXT: ]
 ; OBJ64:      FunctionLineTable [
 ; OBJ64-NEXT:   Name: f
-; OBJ64-NEXT:   Flags: 0x1
+; OBJ64-NEXT:   Flags: 0x0
 ; OBJ64-NEXT:   CodeSize: 0x18
 ; OBJ64-NEXT:   FilenameSegment [
 ; OBJ64-NEXT:     Filename: D:\input.c
@@ -317,8 +191,6 @@
 ; OBJ64-NEXT:       LineNumberStart: 3
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:   ]
 ; OBJ64-NEXT:   FilenameSegment [
@@ -327,8 +199,6 @@
 ; OBJ64-NEXT:       LineNumberStart: 1
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:   ]
 ; OBJ64-NEXT:   FilenameSegment [
@@ -337,8 +207,6 @@
 ; OBJ64-NEXT:       LineNumberStart: 2
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:   ]
 ; OBJ64-NEXT:   FilenameSegment [
@@ -347,15 +215,11 @@
 ; OBJ64-NEXT:       LineNumberStart: 7
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:     +0x13 [
 ; OBJ64-NEXT:       LineNumberStart: 8
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
-; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:   ]
 ; OBJ64-NEXT: ]

Modified: llvm/trunk/test/DebugInfo/COFF/multifunction.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/multifunction.ll?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/multifunction.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/multifunction.ll Thu Jan 28 18:49:42 2016
@@ -24,29 +24,30 @@
 
 ; X86-LABEL: _x:
 ; X86:      # BB
-; X86-NEXT: [[X_CALL:.*]]:{{$}}
+; X86:      .cv_file 1 "D:\\source.c"
+; X86:      .cv_loc 0 1 4 42 is_stmt 0 # source.c:4:42
 ; X86:      calll   _z
-; X86-NEXT: [[X_RETURN:.*]]:
+; X86:      .cv_loc 0 1 5 43 # source.c:5:43
 ; X86:      ret
 ; X86-NEXT: [[END_OF_X:.*]]:
 ;
 ; X86-LABEL: _y:
 ; X86:      # BB
-; X86-NEXT: [[Y_CALL:.*]]:{{$}}
+; X86:      .cv_loc 1 1 8 52 # source.c:8:52
 ; X86:      calll   _z
-; X86-NEXT: [[Y_RETURN:.*]]:
+; X86:      .cv_loc 1 1 9 53 # source.c:9:53
 ; X86:      ret
 ; X86-NEXT: [[END_OF_Y:.*]]:
 ;
 ; X86-LABEL: _f:
 ; X86:      # BB
-; X86-NEXT: [[F_CALLS_X:.*]]:{{$}}
+; X86:      .cv_loc 2 1 12 62 # source.c:12:62
 ; X86:      calll   _x
-; X86-NEXT: [[F_CALLS_Y:.*]]:
+; X86:      .cv_loc 2 1 13 63 # source.c:13:63
 ; X86:      calll   _y
-; X86-NEXT: [[F_CALLS_Z:.*]]:
+; X86:      .cv_loc 2 1 14 72 # source.c:14:72
 ; X86:      calll   _z
-; X86-NEXT: [[F_RETURN:.*]]:
+; X86:      .cv_loc 2 1 15 73 # source.c:15:73
 ; X86:      ret
 ; X86-NEXT: [[END_OF_F:.*]]:
 ;
@@ -74,27 +75,7 @@
 ; Padding
 ; X86-NEXT: .zero   3
 ; Line table subsection for x
-; X86-NEXT: .long   242
-; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X86-NEXT: [[F2_START]]:
-; X86-NEXT: .secrel32       _x
-; X86-NEXT: .secidx _x
-; X86-NEXT: .short 1
-; X86-NEXT: .long [[END_OF_X]]-_x
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   2
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[X_CALL]]-_x
-; X86-NEXT: .long   -2147483644
-; X86-NEXT: .long [[X_RETURN]]-_x
-; X86-NEXT: .long   -2147483643
-; X86-NEXT: .short 42
-; X86-NEXT: .short 0
-; X86-NEXT: .short 43
-; X86-NEXT: .short 0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; X86-NEXT: [[F2_END]]:
+; X86: .cv_linetable 0, _x, [[END_OF_X]]
 ; Symbol subsection for y
 ; X86-NEXT: .long   241
 ; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
@@ -117,27 +98,7 @@
 ; Padding
 ; X86-NEXT: .zero   3
 ; Line table subsection for y
-; X86-NEXT: .long   242
-; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X86-NEXT: [[F2_START]]:
-; X86-NEXT: .secrel32       _y
-; X86-NEXT: .secidx _y
-; X86-NEXT: .short 1
-; X86-NEXT: .long [[END_OF_Y]]-_y
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   2
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[Y_CALL]]-_y
-; X86-NEXT: .long   -2147483640
-; X86-NEXT: .long [[Y_RETURN]]-_y
-; X86-NEXT: .long   -2147483639
-; X86-NEXT: .short 52
-; X86-NEXT: .short 0
-; X86-NEXT: .short 53
-; X86-NEXT: .short 0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; X86-NEXT: [[F2_END]]:
+; X86: .cv_linetable 1, _y, [[END_OF_Y]]
 ; Symbol subsection for f
 ; X86-NEXT: .long   241
 ; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
@@ -160,51 +121,13 @@
 ; Padding
 ; X86-NEXT: .zero   3
 ; Line table subsection for f
-; X86-NEXT: .long   242
-; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X86-NEXT: [[F2_START]]:
-; X86-NEXT: .secrel32 _f
-; X86-NEXT: .secidx _f
-; X86-NEXT: .short 1
-; X86-NEXT: .long [[END_OF_F]]-_f
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   4
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[F_CALLS_X]]-_f
-; X86-NEXT: .long   -2147483636
-; X86-NEXT: .long [[F_CALLS_Y]]-_f
-; X86-NEXT: .long   -2147483635
-; X86-NEXT: .long [[F_CALLS_Z]]-_f
-; X86-NEXT: .long   -2147483634
-; X86-NEXT: .long [[F_RETURN]]-_f
-; X86-NEXT: .long   -2147483633
-; X86-NEXT: .short 62
-; X86-NEXT: .short 0
-; X86-NEXT: .short 63
-; X86-NEXT: .short 0
-; X86-NEXT: .short 72
-; X86-NEXT: .short 0
-; X86-NEXT: .short 73
-; X86-NEXT: .short 0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; X86-NEXT: [[F2_END]]:
-; File index to string table offset subsection
-; X86-NEXT: .long   244
-; X86-NEXT: .long   8
-; X86-NEXT: .long   1
-; X86-NEXT: .long   0
-; String table
-; X86-NEXT: .long   243
-; X86-NEXT: .long   13
-; X86-NEXT: .byte   0
-; X86-NEXT: .ascii  "D:\\source.c"
-; X86-NEXT: .byte   0
-; X86-NEXT: .zero   3
+; X86: .cv_linetable 2, _f, [[END_OF_F]]
+; X86: .cv_filechecksums
+; X86: .cv_stringtable
 
 ; OBJ32:    Section {
 ; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      Characteristics [ (0x42300040)
 ; OBJ32:      ]
 ; OBJ32:      Relocations [
 ; OBJ32-NEXT:   0x2C IMAGE_REL_I386_SECREL _x
@@ -343,40 +266,41 @@
 
 ; X64-LABEL: x:
 ; X64-NEXT: .L{{.*}}:
-; X64-NEXT: [[X_START:.*]]:{{$}}
+; X64:      .cv_file 1 "D:\\source.c"
+; X64:      .cv_loc 0 1 3 0 is_stmt 0 # source.c:3:0
 ; X64:      # BB
 ; X64:      subq    $40, %rsp
-; X64-NEXT: [[X_CALL_LINE:.*]]:{{$}}
+; X64:      .cv_loc 0 1 4 42 # source.c:4:42
 ; X64-NEXT: callq   z
-; X64-NEXT: [[X_EPILOG_AND_RET:.*]]:
+; X64:      .cv_loc 0 1 5 43 # source.c:5:43
 ; X64:      addq    $40, %rsp
 ; X64-NEXT: ret
 ; X64-NEXT: [[END_OF_X:.*]]:
 ;
 ; X64-LABEL: y:
 ; X64-NEXT: .L{{.*}}:
-; X64-NEXT: [[Y_START:.*]]:{{$}}
+; X64:      .cv_loc 1 1 7 0 # source.c:7:0
 ; X64:      # BB
 ; X64:      subq    $40, %rsp
-; X64-NEXT: [[Y_CALL_LINE:.*]]:{{$}}
+; X64:      .cv_loc 1 1 8 52 # source.c:8:52
 ; X64-NEXT: callq   z
-; X64-NEXT: [[Y_EPILOG_AND_RET:.*]]:
+; X64:      .cv_loc 1 1 9 53 # source.c:9:53
 ; X64:      addq    $40, %rsp
 ; X64-NEXT: ret
 ; X64-NEXT: [[END_OF_Y:.*]]:
 ;
 ; X64-LABEL: f:
 ; X64-NEXT: .L{{.*}}:
-; X64-NEXT: [[F_START:.*]]:{{$}}
+; X64:      .cv_loc 2 1 11 0 # source.c:11:0
 ; X64:      # BB
 ; X64:      subq    $40, %rsp
-; X64-NEXT: [[F_CALLS_X:.*]]:{{$}}
+; X64:      .cv_loc 2 1 12 62 # source.c:12:62
 ; X64-NEXT: callq   x
-; X64-NEXT: [[F_CALLS_Y:.*]]:
+; X64:      .cv_loc 2 1 13 63 # source.c:13:63
 ; X64:      callq   y
-; X64-NEXT: [[F_CALLS_Z:.*]]:
+; X64:      .cv_loc 2 1 14 72 # source.c:14:72
 ; X64:      callq   z
-; X64-NEXT: [[F_EPILOG_AND_RET:.*]]:
+; X64:      .cv_loc 2 1 15 73 # source.c:15:73
 ; X64:      addq    $40, %rsp
 ; X64-NEXT: ret
 ; X64-NEXT: [[END_OF_F:.*]]:
@@ -405,31 +329,7 @@
 ; Padding
 ; X64-NEXT: .zero   3
 ; Line table subsection for x
-; X64-NEXT: .long   242
-; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X64-NEXT: [[F2_START]]:
-; X64-NEXT: .secrel32 x
-; X64-NEXT: .secidx x
-; X64-NEXT: .short 1
-; X64-NEXT: .long [[END_OF_X]]-x
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   0
-; X64-NEXT: .long   3
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[X_START]]-x
-; X64-NEXT: .long   -2147483645
-; X64-NEXT: .long [[X_CALL_LINE]]-x
-; X64-NEXT: .long   -2147483644
-; X64-NEXT: .long [[X_EPILOG_AND_RET]]-x
-; X64-NEXT: .long   -2147483643
-; X64-NEXT: .short 0
-; X64-NEXT: .short 0
-; X64-NEXT: .short 42
-; X64-NEXT: .short 0
-; X64-NEXT: .short 43
-; X64-NEXT: .short 0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; X64-NEXT: [[F2_END]]:
+; X64: .cv_linetable 0, x, [[END_OF_X]]
 ; Symbol subsection for y
 ; X64-NEXT: .long   241
 ; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
@@ -452,31 +352,7 @@
 ; Padding
 ; X64-NEXT: .zero   3
 ; Line table subsection for y
-; X64-NEXT: .long   242
-; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X64-NEXT: [[F2_START]]:
-; X64-NEXT: .secrel32 y
-; X64-NEXT: .secidx y
-; X64-NEXT: .short 1
-; X64-NEXT: .long [[END_OF_Y]]-y
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   0
-; X64-NEXT: .long   3
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[Y_START]]-y
-; X64-NEXT: .long   -2147483641
-; X64-NEXT: .long [[Y_CALL_LINE]]-y
-; X64-NEXT: .long   -2147483640
-; X64-NEXT: .long [[Y_EPILOG_AND_RET]]-y
-; X64-NEXT: .long   -2147483639
-; X64-NEXT: .short 0
-; X64-NEXT: .short 0
-; X64-NEXT: .short 52
-; X64-NEXT: .short 0
-; X64-NEXT: .short 53
-; X64-NEXT: .short 0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; X64-NEXT: [[F2_END]]:
+; X64: .cv_linetable 1, y, [[END_OF_Y]]
 ; Symbol subsection for f
 ; X64-NEXT: .long   241
 ; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
@@ -499,55 +375,15 @@
 ; Padding
 ; X64-NEXT: .zero   3
 ; Line table subsection for f
-; X64-NEXT: .long   242
-; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X64-NEXT: [[F2_START]]:
-; X64-NEXT: .secrel32 f
-; X64-NEXT: .secidx f
-; X64-NEXT: .short 1
-; X64-NEXT: .long [[END_OF_F]]-f
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   0
-; X64-NEXT: .long   5
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[F_START]]-f
-; X64-NEXT: .long   -2147483637
-; X64-NEXT: .long [[F_CALLS_X]]-f
-; X64-NEXT: .long   -2147483636
-; X64-NEXT: .long [[F_CALLS_Y]]-f
-; X64-NEXT: .long   -2147483635
-; X64-NEXT: .long [[F_CALLS_Z]]-f
-; X64-NEXT: .long   -2147483634
-; X64-NEXT: .long [[F_EPILOG_AND_RET]]-f
-; X64-NEXT: .long   -2147483633
-; X64-NEXT: .short 0
-; X64-NEXT: .short 0
-; X64-NEXT: .short 62
-; X64-NEXT: .short 0
-; X64-NEXT: .short 63
-; X64-NEXT: .short 0
-; X64-NEXT: .short 72
-; X64-NEXT: .short 0
-; X64-NEXT: .short 73
-; X64-NEXT: .short 0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; X64-NEXT: [[F2_END]]:
+; X64: .cv_linetable 2, f, [[END_OF_F]]
 ; File index to string table offset subsection
-; X64-NEXT: .long   244
-; X64-NEXT: .long   8
-; X64-NEXT: .long   1
-; X64-NEXT: .long   0
+; X64: .cv_filechecksums
 ; String table
-; X64-NEXT: .long   243
-; X64-NEXT: .long   13
-; X64-NEXT: .byte   0
-; X64-NEXT: .ascii  "D:\\source.c"
-; X64-NEXT: .byte   0
-; X64-NEXT: .zero   3
+; X64: .cv_stringtable
 
 ; OBJ64:    Section {
 ; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      Characteristics [ (0x42300040)
 ; OBJ64:      ]
 ; OBJ64:      Relocations [
 ; OBJ64-NEXT:   0x2C IMAGE_REL_AMD64_SECREL x

Modified: llvm/trunk/test/DebugInfo/COFF/simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/simple.ll?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/simple.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/simple.ll Thu Jan 28 18:49:42 2016
@@ -13,9 +13,10 @@
 
 ; X86-LABEL: _f:
 ; X86:      # BB
-; X86-NEXT: [[CALL_LINE:^L.*]]:{{$}}
+; X86:      .cv_file 1 "D:\\test.c"
+; X86:      .cv_loc 0 1 4 2 is_stmt 0 # test.c:4:2
 ; X86:      calll   _g
-; X86-NEXT: [[RETURN_STMT:.*]]:
+; X86:      .cv_loc 0 1 5 0 # test.c:5:0
 ; X86:      ret
 ; X86-NEXT: [[END_OF_F:.*]]:
 ;
@@ -43,44 +44,15 @@
 ; Padding
 ; X86-NEXT: .zero   3
 ; Line table
-; X86-NEXT: .long   242
-; X86-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X86-NEXT: [[F2_START]]:
-; X86-NEXT: .secrel32 _f
-; X86-NEXT: .secidx _f
-; X86-NEXT: .short  1
-; X86-NEXT: .long [[END_OF_F]]-_f
-; X86-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X86-NEXT: .long   0
-; X86-NEXT: .long   2
-; X86-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X86-NEXT: .long [[CALL_LINE]]-_f
-; X86-NEXT: .long   -2147483644
-; X86-NEXT: .long [[RETURN_STMT]]-_f
-; X86-NEXT: .long   -2147483643
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: .short  0
-; X86-NEXT: [[FILE_SEGMENT_END]]:
-; X86-NEXT: [[F2_END]]:
+; X86-NEXT: .cv_linetable 0, _f, [[END_OF_F]]
 ; File index to string table offset subsection
-; X86-NEXT: .long   244
-; X86-NEXT: .long   8
-; X86-NEXT: .long   1
-; X86-NEXT: .long   0
+; X86-NEXT: .cv_filechecksums
 ; String table
-; X86-NEXT: .long   243
-; X86-NEXT: .long   11
-; X86-NEXT: .byte   0
-; X86-NEXT: .ascii  "D:\\test.c"
-; X86-NEXT: .byte   0
-; Padding
-; X86-NEXT: .zero   1
+; X86-NEXT: .cv_stringtable
 
 ; OBJ32:    Section {
 ; OBJ32:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ32:      Characteristics [ (0x42100040)
+; OBJ32:      Characteristics [ (0x42300040)
 ; OBJ32:      ]
 ; OBJ32:      Relocations [
 ; OBJ32-NEXT:   0x2C IMAGE_REL_I386_SECREL _f
@@ -108,7 +80,7 @@
 ; OBJ32-NEXT:       LineNumberStart: 4
 ; OBJ32-NEXT:       LineNumberEndDelta: 0
 ; OBJ32-NEXT:       IsStatement: Yes
-; OBJ32-NEXT:       ColStart: 0
+; OBJ32-NEXT:       ColStart: 2
 ; OBJ32-NEXT:       ColEnd: 0
 ; OBJ32-NEXT:     ]
 ; OBJ32-NEXT:     +0x5 [
@@ -123,12 +95,13 @@
 
 ; X64-LABEL: f:
 ; X64-NEXT: .L{{.*}}:{{$}}
-; X64-NEXT: [[START:.*]]:{{$}}
+; X64:      .cv_file 1 "D:\\test.c"
+; X64:      .cv_loc 0 1 3 0 is_stmt 0 # test.c:3:0
 ; X64:      # BB
 ; X64:      subq    $40, %rsp
-; X64-NEXT: [[CALL_LINE:.*]]:{{$}}
+; X64:      .cv_loc 0 1 4 2 # test.c:4:2
 ; X64-NEXT: callq   g
-; X64-NEXT: [[EPILOG_AND_RET:.*]]:
+; X64:      .cv_loc 0 1 5 0 # test.c:5:0
 ; X64:      addq    $40, %rsp
 ; X64-NEXT: ret
 ; X64-NEXT: [[END_OF_F:.*]]:
@@ -157,48 +130,15 @@
 ; Padding
 ; X64-NEXT: .zero   3
 ; Line table
-; X64-NEXT: .long   242
-; X64-NEXT: .long [[F2_END:.*]]-[[F2_START:.*]]
-; X64-NEXT: [[F2_START]]:
-; X64-NEXT: .secrel32 f
-; X64-NEXT: .secidx f
-; X64-NEXT: .short  1
-; X64-NEXT: .long [[END_OF_F]]-f
-; X64-NEXT: [[FILE_SEGMENT_START:[^:]*]]:
-; X64-NEXT: .long   0
-; X64-NEXT: .long   3
-; X64-NEXT: .long [[FILE_SEGMENT_END:.*]]-[[FILE_SEGMENT_START]]
-; X64-NEXT: .long [[START]]-f
-; X64-NEXT: .long   -2147483645
-; X64-NEXT: .long [[CALL_LINE]]-f
-; X64-NEXT: .long   -2147483644
-; X64-NEXT: .long [[EPILOG_AND_RET]]-f
-; X64-NEXT: .long   -2147483643
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: .short  0
-; X64-NEXT: [[FILE_SEGMENT_END]]:
-; X64-NEXT: [[F2_END]]:
+; X64-NEXT: .cv_linetable 0, f, [[END_OF_F]]
 ; File index to string table offset subsection
-; X64-NEXT: .long   244
-; X64-NEXT: .long   8
-; X64-NEXT: .long   1
-; X64-NEXT: .long   0
+; X64-NEXT: .cv_filechecksums
 ; String table
-; X64-NEXT: .long   243
-; X64-NEXT: .long   11
-; X64-NEXT: .byte   0
-; X64-NEXT: .ascii  "D:\\test.c"
-; X64-NEXT: .byte   0
-; Padding
-; X64-NEXT: .zero   1
+; X64-NEXT: .cv_stringtable
 
 ; OBJ64:    Section {
 ; OBJ64:      Name: .debug$S (2E 64 65 62 75 67 24 53)
-; OBJ64:      Characteristics [ (0x42100040)
+; OBJ64:      Characteristics [ (0x42300040)
 ; OBJ64:      ]
 ; OBJ64:      Relocations [
 ; OBJ64-NEXT:   0x2C IMAGE_REL_AMD64_SECREL f
@@ -233,7 +173,7 @@
 ; OBJ64-NEXT:       LineNumberStart: 4
 ; OBJ64-NEXT:       LineNumberEndDelta: 0
 ; OBJ64-NEXT:       IsStatement: Yes
-; OBJ64-NEXT:       ColStart: 0
+; OBJ64-NEXT:       ColStart: 2
 ; OBJ64-NEXT:       ColEnd: 0
 ; OBJ64-NEXT:     ]
 ; OBJ64-NEXT:     +0x9 [
@@ -274,5 +214,5 @@ attributes #1 = { "less-precise-fpmad"="
 !9 = !{i32 2, !"CodeView", i32 1}
 !10 = !{i32 1, !"Debug Info Version", i32 3}
 !11 = !{!"clang version 3.5 "}
-!12 = !DILocation(line: 4, scope: !4)
+!12 = !DILocation(line: 4, column: 2, scope: !4)
 !13 = !DILocation(line: 5, scope: !4)

Modified: llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/tail-call-without-lexical-scopes.ll Thu Jan 28 18:49:42 2016
@@ -15,10 +15,10 @@
 ; The bar function happens to have no lexical scopes, yet it has one instruction
 ; with debug information available.  This used to be PR19239.
 
+; X86:      .cv_file 1 "D:\\test.cpp"
+
 ; X86-LABEL: {{^}}"?bar@@YAXHZZ":
-; X86-NEXT: L{{.*}}:
-; X86-NEXT: # BB
-; X86-NEXT: [[JMP_LINE:^L.*]]:{{$}}
+; X86:      .cv_loc  1 1 4 0
 ; X86:      jmp "?foo@@YAXXZ"
 ; X86-NEXT: [[END_OF_BAR:^L.*]]:{{$}}
 ; X86-NOT:  ret
@@ -26,13 +26,9 @@
 ; X86-LABEL: .section        .debug$S,"dr"
 ; X86:       .secrel32 "?bar@@YAXHZZ"
 ; X86-NEXT:  .secidx   "?bar@@YAXHZZ"
-; X86:       .long   0
-; X86-NEXT:  .long   1
-; X86-NEXT:  .long {{.*}}
-; X86-NEXT:  .long [[JMP_LINE]]-"?bar@@YAXHZZ"
-; X86-NEXT:  .long   -2147483644
-
-; X86-LABEL: .long   244
+; X86:       .cv_linetable 1, "?bar@@YAXHZZ", [[END_OF_BAR]]
+; X86:       .cv_filechecksums
+; X86:       .cv_stringtable
 
 ; ModuleID = 'test.cpp'
 target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"

Added: llvm/trunk/test/MC/COFF/cv-loc.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-loc.s?rev=259130&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-loc.s (added)
+++ llvm/trunk/test/MC/COFF/cv-loc.s Thu Jan 28 18:49:42 2016
@@ -0,0 +1,85 @@
+# RUN: llvm-mc < %s -triple=x86_64-pc-win32 -filetype=obj | llvm-readobj - -codeview | FileCheck %s
+
+.section .debug$S
+.long 4
+.cv_stringtable
+
+.cv_file 1 "a.c"
+.cv_file 2 "t.inc"
+
+# Implements this C:
+# void f(volatile int *x) {
+#   ++*x;
+# #include "t.h" // contains two ++*x; statements
+#   ++*x;
+# }
+
+.text
+.def     f;
+        .scl    2;
+        .type   32;
+        .endef
+        .text
+        .globl  f
+        .align  16, 0x90
+f:
+.Lfunc_begin0:
+  .cv_loc 0 1 5 2
+  incl (%rdi)
+  # #include "t.h" start
+  .cv_loc 0 2 0 0
+  incl (%rdi)
+  .cv_loc 0 2 1 0
+  incl (%rdi)
+  # #include "t.h" end
+  .cv_loc 0 1 6 2
+  incl (%rdi)
+  retq
+.Lfunc_end0:
+
+.section .debug$S
+.cv_filechecksums
+.cv_linetable 0, f, .Lfunc_end0
+
+# CHECK: FunctionLineTable [
+# CHECK:   LinkageName: f
+# CHECK:   Flags: 0x1
+# CHECK:   CodeSize: 0x9
+# CHECK:   FilenameSegment [
+# CHECK:     Filename: a.c (0x0)
+# CHECK:     +0x0 [
+# CHECK:       LineNumberStart: 5
+# CHECK:       LineNumberEndDelta: 0
+# CHECK:       IsStatement: Yes
+# CHECK:       ColStart: 2
+# CHECK:       ColEnd: 0
+# CHECK:     ]
+# CHECK:   ]
+# CHECK:   FilenameSegment [
+# CHECK:     Filename: t.inc (0x8)
+# CHECK:     +0x2 [
+# CHECK:       LineNumberStart: 0
+# CHECK:       LineNumberEndDelta: 0
+# CHECK:       IsStatement: Yes
+# CHECK:       ColStart: 0
+# CHECK:       ColEnd: 0
+# CHECK:     ]
+# CHECK:     +0x4 [
+# CHECK:       LineNumberStart: 1
+# CHECK:       LineNumberEndDelta: 0
+# CHECK:       IsStatement: Yes
+# CHECK:       ColStart: 0
+# CHECK:       ColEnd: 0
+# CHECK:     ]
+# CHECK:   ]
+# CHECK:   FilenameSegment [
+# CHECK:     Filename: a.c (0x0)
+# CHECK:     +0x6 [
+# CHECK:       LineNumberStart: 6
+# CHECK:       LineNumberEndDelta: 0
+# CHECK:       IsStatement: Yes
+# CHECK:       ColStart: 2
+# CHECK:       ColEnd: 0
+# CHECK:     ]
+# CHECK:   ]
+# CHECK: ]

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Thu Jan 28 18:49:42 2016
@@ -1116,8 +1116,7 @@ void COFFDumper::printCodeViewSymbolSect
     uint32_t Offset = 6;  // Skip relocations.
     uint16_t Flags = DE.getU16(&Offset);
     W.printHex("Flags", Flags);
-    bool HasColumnInformation =
-        Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS;
+    bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns;
     uint32_t FunctionSize = DE.getU32(&Offset);
     W.printHex("CodeSize", FunctionSize);
     while (DE.isValidOffset(Offset)) {
@@ -1151,11 +1150,11 @@ void COFFDumper::printCodeViewSymbolSect
         char Buffer[32];
         format("+0x%X", PC).snprint(Buffer, 32);
         ListScope PCScope(W, Buffer);
-        uint32_t LineNumberStart = LineData & COFF::CVL_MaxLineNumber;
+        uint32_t LineNumberStart = LineData & codeview::LineInfo::StartLineMask;
         uint32_t LineNumberEndDelta =
-            (LineData >> COFF::CVL_LineNumberStartBits) &
-            COFF::CVL_LineNumberEndDeltaMask;
-        bool IsStatement = LineData & COFF::CVL_IsStatement;
+            (LineData & codeview::LineInfo::EndLineDeltaMask) >>
+            codeview::LineInfo::EndLineDeltaShift;
+        bool IsStatement = codeview::LineInfo::StatementFlag;
         W.printNumber("LineNumberStart", LineNumberStart);
         W.printNumber("LineNumberEndDelta", LineNumberEndDelta);
         W.printBoolean("IsStatement", IsStatement);

Modified: llvm/trunk/unittests/MC/StringTableBuilderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/MC/StringTableBuilderTest.cpp?rev=259130&r1=259129&r2=259130&view=diff
==============================================================================
--- llvm/trunk/unittests/MC/StringTableBuilderTest.cpp (original)
+++ llvm/trunk/unittests/MC/StringTableBuilderTest.cpp Thu Jan 28 18:49:42 2016
@@ -68,4 +68,27 @@ TEST(StringTableBuilderTest, BasicWinCOF
   EXPECT_EQ(23U, B.getOffset("river horse"));
 }
 
+TEST(StringTableBuilderTest, ELFInOrder) {
+  StringTableBuilder B(StringTableBuilder::ELF);
+  EXPECT_EQ(1U, B.add("foo"));
+  EXPECT_EQ(5U, B.add("bar"));
+  EXPECT_EQ(9U, B.add("foobar"));
+
+  B.finalizeInOrder();
+
+  std::string Expected;
+  Expected += '\x00';
+  Expected += "foo";
+  Expected += '\x00';
+  Expected += "bar";
+  Expected += '\x00';
+  Expected += "foobar";
+  Expected += '\x00';
+
+  EXPECT_EQ(Expected, B.data());
+  EXPECT_EQ(1U, B.getOffset("foo"));
+  EXPECT_EQ(5U, B.getOffset("bar"));
+  EXPECT_EQ(9U, B.getOffset("foobar"));
+}
+
 }




More information about the llvm-commits mailing list