[llvm] r280822 - [codeview] Add new directives to record inlined call site line info

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 7 09:15:32 PDT 2016


Author: rnk
Date: Wed Sep  7 11:15:31 2016
New Revision: 280822

URL: http://llvm.org/viewvc/llvm-project?rev=280822&view=rev
Log:
[codeview] Add new directives to record inlined call site line info

Summary:
Previously we were trying to represent this with the "contains" list of
the .cv_inline_linetable directive, which was not enough information.
Now we directly represent the chain of inlined call sites, so we know
what location to emit when we encounter a .cv_loc directive of an inner
inlined call site while emitting the line table of an outer function or
inlined call site. Fixes PR29146.

Also fixes PR29147, where we would crash when .cv_loc directives crossed
sections. Now we write down the section of the first .cv_loc directive,
and emit an error if any other .cv_loc directive for that function is in
a different section.

Also fixes issues with discontiguous inlined source locations, like in
this example:

  volatile int unlikely_cond = 0;
  extern void __declspec(noreturn) abort();
  __forceinline void f() {
    if (!unlikely_cond) abort();
  }
  int main() {
    unlikely_cond = 0;
    f();
    unlikely_cond = 0;
  }

Previously our tables gave bad location information for the 'abort'
call, and the debugger wouldn't snow the inlined stack frame for 'f'.
It is important to emit good line tables for this code pattern, because
it comes up whenever an asan bug occurs in an inlined function. The
__asan_report* stubs are generally placed after the normal function
epilogue, leading to discontiguous regions of inlined code.

Reviewers: majnemer, amccarth

Subscribers: llvm-commits

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

Added:
    llvm/trunk/test/MC/COFF/cv-errors.s
    llvm/trunk/test/MC/COFF/cv-inline-linetable-unlikely.s
    llvm/trunk/test/MC/COFF/cv-loc-cross-section.s
Modified:
    llvm/trunk/include/llvm/MC/MCCodeView.h
    llvm/trunk/include/llvm/MC/MCFragment.h
    llvm/trunk/include/llvm/MC/MCObjectStreamer.h
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/MC/MCAsmStreamer.cpp
    llvm/trunk/lib/MC/MCCodeView.cpp
    llvm/trunk/lib/MC/MCObjectStreamer.cpp
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp
    llvm/trunk/lib/MC/MCStreamer.cpp
    llvm/trunk/test/DebugInfo/COFF/inlining-header.ll
    llvm/trunk/test/DebugInfo/COFF/inlining-levels.ll
    llvm/trunk/test/DebugInfo/COFF/inlining.ll
    llvm/trunk/test/DebugInfo/COFF/local-variables.ll
    llvm/trunk/test/MC/COFF/cv-def-range.s
    llvm/trunk/test/MC/COFF/cv-empty-linetable.s
    llvm/trunk/test/MC/COFF/cv-inline-linetable-infloop.s
    llvm/trunk/test/MC/COFF/cv-inline-linetable-unreachable.s
    llvm/trunk/test/MC/COFF/cv-inline-linetable.s
    llvm/trunk/test/MC/COFF/cv-loc.s

Modified: llvm/trunk/include/llvm/MC/MCCodeView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCCodeView.h?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCCodeView.h (original)
+++ llvm/trunk/include/llvm/MC/MCCodeView.h Wed Sep  7 11:15:31 2016
@@ -105,6 +105,55 @@ public:
   static void Make(MCObjectStreamer *MCOS);
 };
 
+/// Information describing a function or inlined call site introduced by
+/// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
+/// directives used with this function's id or the id of an inlined call site
+/// within this function or inlined call site.
+struct MCCVFunctionInfo {
+  /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
+  /// the parent function id plus one. If this represents a normal function,
+  /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
+  /// If this struct is an unallocated slot in the function info vector, then
+  /// ParentFuncIdPlusOne will be zero.
+  unsigned ParentFuncIdPlusOne = 0;
+
+  enum : unsigned { FunctionSentinel = ~0U };
+
+  struct LineInfo {
+    unsigned File;
+    unsigned Line;
+    unsigned Col;
+  };
+
+  LineInfo InlinedAt;
+
+  /// The section of the first .cv_loc directive used for this function, or null
+  /// if none has been seen yet.
+  MCSection *Section = nullptr;
+
+  /// Map from inlined call site id to the inlined at location to use for that
+  /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
+  /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
+  /// list the line info for the 'g' call site.
+  DenseMap<unsigned, LineInfo> InlinedAtMap;
+
+  /// Returns true if this is function info has not yet been used in a
+  /// .cv_func_id or .cv_inline_site_id directive.
+  bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
+
+  /// Returns true if this represents an inlined call site, meaning
+  /// ParentFuncIdPlusOne is neither zero nor ~0U.
+  bool isInlinedCallSite() const {
+    return !isUnallocatedFunctionInfo() &&
+           ParentFuncIdPlusOne != FunctionSentinel;
+  }
+
+  unsigned getParentFuncId() const {
+    assert(isInlinedCallSite());
+    return ParentFuncIdPlusOne - 1;
+  }
+};
+
 /// Holds state from .cv_file and .cv_loc directives for later emission.
 class CodeViewContext {
 public:
@@ -115,6 +164,27 @@ public:
   bool addFile(unsigned FileNumber, StringRef Filename);
   ArrayRef<StringRef> getFilenames() { return Filenames; }
 
+  /// Records the function id of a normal function. Returns false if the
+  /// function id has already been used, and true otherwise.
+  bool recordFunctionId(unsigned FuncId);
+
+  /// Records the function id of an inlined call site. Records the "inlined at"
+  /// location info of the call site, including what function or inlined call
+  /// site it was inlined into. Returns false if the function id has already
+  /// been used, and true otherwise.
+  bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
+                               unsigned IAFile, unsigned IALine,
+                               unsigned IACol);
+
+  /// Retreive the function info if this is a valid function id, or nullptr.
+  MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId) {
+    if (FuncId >= Functions.size())
+      return nullptr;
+    if (Functions[FuncId].isUnallocatedFunctionInfo())
+      return nullptr;
+    return &Functions[FuncId];
+  }
+
   /// 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
@@ -179,10 +249,12 @@ public:
                                 const MCSymbol *FuncBegin,
                                 const MCSymbol *FuncEnd);
 
-  void emitInlineLineTableForFunction(
-      MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
-      unsigned SourceLineNum, const MCSymbol *FnStartSym,
-      const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds);
+  void emitInlineLineTableForFunction(MCObjectStreamer &OS,
+                                      unsigned PrimaryFunctionId,
+                                      unsigned SourceFileId,
+                                      unsigned SourceLineNum,
+                                      const MCSymbol *FnStartSym,
+                                      const MCSymbol *FnEndSym);
 
   /// Encodes the binary annotations once we have a layout.
   void encodeInlineLineTable(MCAsmLayout &Layout,
@@ -230,6 +302,9 @@ private:
 
   /// A collection of MCCVLineEntry for each section.
   std::vector<MCCVLineEntry> MCCVLines;
+
+  /// All known functions and inlined call sites, indexed by function id.
+  std::vector<MCCVFunctionInfo> Functions;
 };
 
 } // end namespace llvm

Modified: llvm/trunk/include/llvm/MC/MCFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCFragment.h?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCFragment.h (original)
+++ llvm/trunk/include/llvm/MC/MCFragment.h Wed Sep  7 11:15:31 2016
@@ -491,7 +491,6 @@ class MCCVInlineLineTableFragment : publ
   unsigned StartLineNum;
   const MCSymbol *FnStartSym;
   const MCSymbol *FnEndSym;
-  SmallVector<unsigned, 3> SecondaryFuncs;
   SmallString<8> Contents;
 
   /// CodeViewContext has the real knowledge about this format, so let it access
@@ -502,12 +501,10 @@ public:
   MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
                               unsigned StartLineNum, const MCSymbol *FnStartSym,
                               const MCSymbol *FnEndSym,
-                              ArrayRef<unsigned> SecondaryFuncs,
                               MCSection *Sec = nullptr)
       : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId),
         StartFileId(StartFileId), StartLineNum(StartLineNum),
-        FnStartSym(FnStartSym), FnEndSym(FnEndSym),
-        SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) {}
+        FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
 
   /// \name Accessors
   /// @{

Modified: llvm/trunk/include/llvm/MC/MCObjectStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCObjectStreamer.h?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCObjectStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h Wed Sep  7 11:15:31 2016
@@ -124,13 +124,14 @@ public:
                                  const MCSymbol *Label);
   void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
                           unsigned Column, bool PrologueEnd, bool IsStmt,
-                          StringRef FileName) override;
+                          StringRef FileName, SMLoc Loc) override;
   void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *Begin,
                                 const MCSymbol *End) override;
-  void EmitCVInlineLinetableDirective(
-      unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
-      const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
-      ArrayRef<unsigned> SecondaryFunctionIds) override;
+  void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+                                      unsigned SourceFileId,
+                                      unsigned SourceLineNum,
+                                      const MCSymbol *FnStartSym,
+                                      const MCSymbol *FnEndSym) override;
   void EmitCVDefRangeDirective(
       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
       StringRef FixedSizePortion) override;

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Wed Sep  7 11:15:31 2016
@@ -713,11 +713,20 @@ public:
   /// success.
   virtual bool EmitCVFileDirective(unsigned FileNo, StringRef Filename);
 
+  /// \brief Introduces a function id for use with .cv_loc.
+  virtual bool EmitCVFuncIdDirective(unsigned FunctionId);
+
+  /// \brief Introduces an inline call site id for use with .cv_loc. Includes
+  /// extra information for inline line table generation.
+  virtual bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
+                                           unsigned IAFile, unsigned IALine,
+                                           unsigned IACol, SMLoc Loc);
+
   /// \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);
+                                  StringRef FileName, SMLoc Loc);
 
   /// \brief This implements the CodeView '.cv_linetable' assembler directive.
   virtual void EmitCVLinetableDirective(unsigned FunctionId,
@@ -726,10 +735,11 @@ public:
 
   /// \brief This implements the CodeView '.cv_inline_linetable' assembler
   /// directive.
-  virtual void EmitCVInlineLinetableDirective(
-      unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
-      const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
-      ArrayRef<unsigned> SecondaryFunctionIds);
+  virtual void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+                                              unsigned SourceFileId,
+                                              unsigned SourceLineNum,
+                                              const MCSymbol *FnStartSym,
+                                              const MCSymbol *FnEndSym);
 
   /// \brief This implements the CodeView '.cv_def_range' assembler
   /// directive.

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Wed Sep  7 11:15:31 2016
@@ -124,7 +124,16 @@ CodeViewDebug::getInlineSite(const DILoc
   auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
   InlineSite *Site = &SiteInsertion.first->second;
   if (SiteInsertion.second) {
+    unsigned ParentFuncId = CurFn->FuncId;
+    if (const DILocation *OuterIA = InlinedAt->getInlinedAt())
+      ParentFuncId =
+          getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
+              .SiteFuncId;
+
     Site->SiteFuncId = NextFuncId++;
+    OS.EmitCVInlineSiteIdDirective(
+        Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
+        InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
     Site->Inlinee = Inlinee;
     InlinedSubprograms.insert(Inlinee);
     getFuncIdForSubprogram(Inlinee);
@@ -357,8 +366,8 @@ void CodeViewDebug::maybeRecordLocation(
   }
 
   OS.EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(),
-                        /*PrologueEnd=*/false,
-                        /*IsStmt=*/false, DL->getFilename());
+                        /*PrologueEnd=*/false, /*IsStmt=*/false,
+                        DL->getFilename(), SMLoc());
 }
 
 void CodeViewDebug::emitCodeViewMagicVersion() {
@@ -529,17 +538,6 @@ void CodeViewDebug::emitInlineeLinesSubs
   endCVSubsection(InlineEnd);
 }
 
-void CodeViewDebug::collectInlineSiteChildren(
-    SmallVectorImpl<unsigned> &Children, const FunctionInfo &FI,
-    const InlineSite &Site) {
-  for (const DILocation *ChildSiteLoc : Site.ChildSites) {
-    auto I = FI.InlineSites.find(ChildSiteLoc);
-    const InlineSite &ChildSite = I->second;
-    Children.push_back(ChildSite.SiteFuncId);
-    collectInlineSiteChildren(Children, FI, ChildSite);
-  }
-}
-
 void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
                                         const DILocation *InlinedAt,
                                         const InlineSite &Site) {
@@ -565,11 +563,9 @@ void CodeViewDebug::emitInlinedCallSite(
 
   unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
   unsigned StartLineNum = Site.Inlinee->getLine();
-  SmallVector<unsigned, 3> SecondaryFuncIds;
-  collectInlineSiteChildren(SecondaryFuncIds, FI, Site);
 
   OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
-                                    FI.Begin, FI.End, SecondaryFuncIds);
+                                    FI.Begin, FI.End);
 
   OS.EmitLabel(InlineEnd);
 
@@ -877,6 +873,8 @@ void CodeViewDebug::beginFunction(const
   CurFn->FuncId = NextFuncId++;
   CurFn->Begin = Asm->getFunctionBegin();
 
+  OS.EmitCVFuncIdDirective(CurFn->FuncId);
+
   // Find the end of the function prolog.  First known non-DBG_VALUE and
   // non-frame setup location marks the beginning of the function body.
   // FIXME: is there a simpler a way to do this? Can we just search

Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Wed Sep  7 11:15:31 2016
@@ -222,15 +222,20 @@ public:
   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
 
   bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
+  bool EmitCVFuncIdDirective(unsigned FuncId) override;
+  bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
+                                   unsigned IAFile, unsigned IALine,
+                                   unsigned IACol, SMLoc Loc) override;
   void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
                           unsigned Column, bool PrologueEnd, bool IsStmt,
-                          StringRef FileName) override;
+                          StringRef FileName, SMLoc Loc) override;
   void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
                                 const MCSymbol *FnEnd) override;
-  void EmitCVInlineLinetableDirective(
-      unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
-      const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
-      ArrayRef<unsigned> SecondaryFunctionIds) override;
+  void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+                                      unsigned SourceFileId,
+                                      unsigned SourceLineNum,
+                                      const MCSymbol *FnStartSym,
+                                      const MCSymbol *FnEndSym) override;
   void EmitCVDefRangeDirective(
       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
       StringRef FixedSizePortion) override;
@@ -1114,10 +1119,26 @@ bool MCAsmStreamer::EmitCVFileDirective(
   return true;
 }
 
+bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
+  OS << "\t.cv_func_id " << FuncId << '\n';
+  return MCStreamer::EmitCVFuncIdDirective(FuncId);
+}
+
+bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
+                                                unsigned IAFunc,
+                                                unsigned IAFile,
+                                                unsigned IALine, unsigned IACol,
+                                                SMLoc Loc) {
+  OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
+     << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
+  return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
+                                                 IALine, IACol, Loc);
+}
+
 void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
                                        unsigned Line, unsigned Column,
                                        bool PrologueEnd, bool IsStmt,
-                                       StringRef FileName) {
+                                       StringRef FileName, SMLoc Loc) {
   OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
      << Column;
   if (PrologueEnd)
@@ -1135,12 +1156,12 @@ void MCAsmStreamer::EmitCVLocDirective(u
 
   if (IsVerboseAsm) {
     OS.PadToColumn(MAI->getCommentColumn());
-    OS << MAI->getCommentString() << ' ' << FileName << ':'
-       << Line << ':' << Column;
+    OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
+       << Column;
   }
   EmitEOL();
   this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
-                                       PrologueEnd, IsStmt, FileName);
+                                       PrologueEnd, IsStmt, FileName, Loc);
 }
 
 void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -1154,24 +1175,19 @@ void MCAsmStreamer::EmitCVLinetableDirec
   this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
 }
 
-void MCAsmStreamer::EmitCVInlineLinetableDirective(
-    unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
-    const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
-    ArrayRef<unsigned> SecondaryFunctionIds) {
+void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+                                                   unsigned SourceFileId,
+                                                   unsigned SourceLineNum,
+                                                   const MCSymbol *FnStartSym,
+                                                   const MCSymbol *FnEndSym) {
   OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
      << ' ' << SourceLineNum << ' ';
   FnStartSym->print(OS, MAI);
   OS << ' ';
   FnEndSym->print(OS, MAI);
-  if (!SecondaryFunctionIds.empty()) {
-    OS << " contains";
-    for (unsigned SecondaryFunctionId : SecondaryFunctionIds)
-      OS << ' ' << SecondaryFunctionId;
-  }
   EmitEOL();
   this->MCStreamer::EmitCVInlineLinetableDirective(
-      PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
-      SecondaryFunctionIds);
+      PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
 }
 
 void MCAsmStreamer::EmitCVDefRangeDirective(

Modified: llvm/trunk/lib/MC/MCCodeView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCCodeView.cpp?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCCodeView.cpp (original)
+++ llvm/trunk/lib/MC/MCCodeView.cpp Wed Sep  7 11:15:31 2016
@@ -65,6 +65,50 @@ bool CodeViewContext::addFile(unsigned F
   return true;
 }
 
+bool CodeViewContext::recordFunctionId(unsigned FuncId) {
+  if (FuncId >= Functions.size())
+    Functions.resize(FuncId + 1);
+
+  // Return false if this function info was already allocated.
+  if (!Functions[FuncId].isUnallocatedFunctionInfo())
+    return false;
+
+  // Mark this as an allocated normal function, and leave the rest alone.
+  Functions[FuncId].ParentFuncIdPlusOne = MCCVFunctionInfo::FunctionSentinel;
+  return true;
+}
+
+bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
+                                              unsigned IAFile, unsigned IALine,
+                                              unsigned IACol) {
+  if (FuncId >= Functions.size())
+    Functions.resize(FuncId + 1);
+
+  // Return false if this function info was already allocated.
+  if (!Functions[FuncId].isUnallocatedFunctionInfo())
+    return false;
+
+  MCCVFunctionInfo::LineInfo InlinedAt;
+  InlinedAt.File = IAFile;
+  InlinedAt.Line = IALine;
+  InlinedAt.Col = IACol;
+
+  // Mark this as an inlined call site and record call site line info.
+  MCCVFunctionInfo *Info = &Functions[FuncId];
+  Info->ParentFuncIdPlusOne = IAFunc + 1;
+  Info->InlinedAt = InlinedAt;
+
+  // Walk up the call chain adding this function id to the InlinedAtMap of all
+  // transitive callers until we hit a real function.
+  while (Info->isInlinedCallSite()) {
+    InlinedAt = Info->InlinedAt;
+    Info = getCVFunctionInfo(Info->getParentFuncId());
+    Info->InlinedAtMap[FuncId] = InlinedAt;
+  }
+
+  return true;
+}
+
 MCDataFragment *CodeViewContext::getStringTableFragment() {
   if (!StrTabFragment) {
     StrTabFragment = new MCDataFragment();
@@ -237,15 +281,17 @@ static uint32_t encodeSignedNumber(uint3
   return Data << 1;
 }
 
-void CodeViewContext::emitInlineLineTableForFunction(
-    MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
-    unsigned SourceLineNum, const MCSymbol *FnStartSym,
-    const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds) {
+void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS,
+                                                     unsigned PrimaryFunctionId,
+                                                     unsigned SourceFileId,
+                                                     unsigned SourceLineNum,
+                                                     const MCSymbol *FnStartSym,
+                                                     const MCSymbol *FnEndSym) {
   // Create and insert a fragment into the current section that will be encoded
   // later.
-  new MCCVInlineLineTableFragment(
-      PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
-      SecondaryFunctionIds, OS.getCurrentSectionOnly());
+  new MCCVInlineLineTableFragment(PrimaryFunctionId, SourceFileId,
+                                  SourceLineNum, FnStartSym, FnEndSym,
+                                  OS.getCurrentSectionOnly());
 }
 
 void CodeViewContext::emitDefRange(
@@ -280,69 +326,83 @@ void CodeViewContext::encodeInlineLineTa
   size_t LocBegin;
   size_t LocEnd;
   std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
-  for (unsigned SecondaryId : Frag.SecondaryFuncs) {
-    auto Extent = getLineExtent(SecondaryId);
+
+  // Include all child inline call sites in our .cv_loc extent.
+  MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
+  for (auto &KV : SiteInfo->InlinedAtMap) {
+    unsigned ChildId = KV.first;
+    auto Extent = getLineExtent(ChildId);
     LocBegin = std::min(LocBegin, Extent.first);
     LocEnd = std::max(LocEnd, Extent.second);
   }
+
   if (LocBegin >= LocEnd)
     return;
   ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
   if (Locs.empty())
     return;
 
-  SmallSet<unsigned, 8> InlinedFuncIds;
-  InlinedFuncIds.insert(Frag.SiteFuncId);
-  InlinedFuncIds.insert(Frag.SecondaryFuncs.begin(), Frag.SecondaryFuncs.end());
-
   // Make an artificial start location using the function start and the inlinee
   // lines start location information. All deltas start relative to this
   // location.
   MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front()));
   StartLoc.setFileNum(Frag.StartFileId);
   StartLoc.setLine(Frag.StartLineNum);
-  const MCCVLineEntry *LastLoc = &StartLoc;
   bool HaveOpenRange = false;
 
+  const MCSymbol *LastLabel = Frag.getFnStartSym();
+  MCCVFunctionInfo::LineInfo LastSourceLoc, CurSourceLoc;
+  LastSourceLoc.File = Frag.StartFileId;
+  LastSourceLoc.Line = Frag.StartLineNum;
+
   SmallVectorImpl<char> &Buffer = Frag.getContents();
   Buffer.clear(); // Clear old contents if we went through relaxation.
   for (const MCCVLineEntry &Loc : Locs) {
-    if (!InlinedFuncIds.count(Loc.getFunctionId())) {
-      // We've hit a cv_loc not attributed to this inline call site. Use this
-      // label to end the PC range.
-      if (HaveOpenRange) {
-        unsigned Length =
-            computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
-        compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
-        compressAnnotation(Length, Buffer);
+    if (Loc.getFunctionId() == Frag.SiteFuncId) {
+      CurSourceLoc.File = Loc.getFileNum();
+      CurSourceLoc.Line = Loc.getLine();
+    } else {
+      auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId());
+      if (I != SiteInfo->InlinedAtMap.end()) {
+        // This .cv_loc is from a child inline call site. Use the source
+        // location of the inlined call site instead of the .cv_loc directive
+        // source location.
+        CurSourceLoc = I->second;
+      } else {
+        // We've hit a cv_loc not attributed to this inline call site. Use this
+        // label to end the PC range.
+        if (HaveOpenRange) {
+          unsigned Length = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
+          compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
+          compressAnnotation(Length, Buffer);
+          LastLabel = Loc.getLabel();
+        }
+        HaveOpenRange = false;
+        continue;
       }
-      HaveOpenRange = false;
-      continue;
     }
 
-    // If we've already opened the function and we're at an indirectly inlined
-    // location, continue until the next directly inlined location.
-    bool DirectlyInlined = Loc.getFunctionId() == Frag.SiteFuncId;
-    if (!DirectlyInlined && HaveOpenRange)
+    // Skip this .cv_loc if we have an open range and this isn't a meaningful
+    // source location update. The current table format does not support column
+    // info, so we can skip updates for those.
+    if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File &&
+        CurSourceLoc.Line == LastSourceLoc.Line)
       continue;
+
     HaveOpenRange = true;
 
-    if (Loc.getFileNum() != LastLoc->getFileNum()) {
+    if (CurSourceLoc.File != LastSourceLoc.File) {
       // File ids are 1 based, and each file checksum table entry is 8 bytes
       // long. See emitFileChecksums above.
-      unsigned FileOffset = 8 * (Loc.getFileNum() - 1);
+      unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
       compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
       compressAnnotation(FileOffset, Buffer);
     }
 
-    int LineDelta = Loc.getLine() - LastLoc->getLine();
-    if (LineDelta == 0)
-      continue;
-
+    int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line;
     unsigned EncodedLineDelta = encodeSignedNumber(LineDelta);
-    unsigned CodeDelta =
-        computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
-    if (CodeDelta == 0) {
+    unsigned CodeDelta = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
+    if (CodeDelta == 0 && LineDelta != 0) {
       compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
       compressAnnotation(EncodedLineDelta, Buffer);
     } else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {
@@ -355,29 +415,29 @@ void CodeViewContext::encodeInlineLineTa
       compressAnnotation(Operand, Buffer);
     } else {
       // Otherwise use the separate line and code deltas.
-      compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
-      compressAnnotation(EncodedLineDelta, Buffer);
+      if (LineDelta != 0) {
+        compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
+        compressAnnotation(EncodedLineDelta, Buffer);
+      }
       compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer);
       compressAnnotation(CodeDelta, Buffer);
     }
 
-    LastLoc = &Loc;
+    LastLabel = Loc.getLabel();
+    LastSourceLoc = CurSourceLoc;
   }
 
   assert(HaveOpenRange);
 
   unsigned EndSymLength =
-      computeLabelDiff(Layout, LastLoc->getLabel(), Frag.getFnEndSym());
+      computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym());
   unsigned LocAfterLength = ~0U;
   ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
   if (!LocAfter.empty()) {
     // Only try to compute this difference if we're in the same section.
     const MCCVLineEntry &Loc = LocAfter[0];
-    if (&Loc.getLabel()->getSection(false) ==
-        &LastLoc->getLabel()->getSection(false)) {
-      LocAfterLength =
-          computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
-    }
+    if (&Loc.getLabel()->getSection(false) == &LastLabel->getSection(false))
+      LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
   }
 
   compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);

Modified: llvm/trunk/lib/MC/MCObjectStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectStreamer.cpp?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectStreamer.cpp Wed Sep  7 11:15:31 2016
@@ -369,13 +369,13 @@ void MCObjectStreamer::EmitDwarfAdvanceF
 void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
                                           unsigned Line, unsigned Column,
                                           bool PrologueEnd, bool IsStmt,
-                                          StringRef FileName) {
+                                          StringRef FileName, SMLoc Loc) {
   // 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);
+                                       PrologueEnd, IsStmt, FileName, Loc);
 }
 
 void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
@@ -388,14 +388,12 @@ void MCObjectStreamer::EmitCVLinetableDi
 
 void MCObjectStreamer::EmitCVInlineLinetableDirective(
     unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
-    const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
-    ArrayRef<unsigned> SecondaryFunctionIds) {
+    const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
   getContext().getCVContext().emitInlineLineTableForFunction(
       *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
-      FnEndSym, SecondaryFunctionIds);
+      FnEndSym);
   this->MCStreamer::EmitCVInlineLinetableDirective(
-      PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
-      SecondaryFunctionIds);
+      PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
 }
 
 void MCObjectStreamer::EmitCVDefRangeDirective(

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Wed Sep  7 11:15:31 2016
@@ -378,6 +378,9 @@ private:
 
   bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc);
 
+  bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName);
+  bool parseCVFileId(int64_t &FileId, StringRef DirectiveName);
+
   // Generic (target and platform independent) directive parsing.
   enum DirectiveKind {
     DK_NO_DIRECTIVE, // Placeholder
@@ -397,8 +400,9 @@ 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_INLINE_LINETABLE,
-    DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS,
+    DK_CV_FILE, DK_CV_FUNC_ID, DK_CV_INLINE_SITE_ID, DK_CV_LOC, DK_CV_LINETABLE,
+    DK_CV_INLINE_LINETABLE, DK_CV_DEF_RANGE, 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,
@@ -436,9 +440,11 @@ private:
   bool parseDirectiveLoc();
   bool parseDirectiveStabs();
 
-  // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable",
-  // ".cv_def_range"
+  // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable",
+  // ".cv_inline_linetable", ".cv_def_range"
   bool parseDirectiveCVFile();
+  bool parseDirectiveCVFuncId();
+  bool parseDirectiveCVInlineSiteId();
   bool parseDirectiveCVLoc();
   bool parseDirectiveCVLinetable();
   bool parseDirectiveCVInlineLinetable();
@@ -1790,6 +1796,10 @@ bool AsmParser::parseStatement(ParseStat
       return parseDirectiveStabs();
     case DK_CV_FILE:
       return parseDirectiveCVFile();
+    case DK_CV_FUNC_ID:
+      return parseDirectiveCVFuncId();
+    case DK_CV_INLINE_SITE_ID:
+      return parseDirectiveCVInlineSiteId();
     case DK_CV_LOC:
       return parseDirectiveCVLoc();
     case DK_CV_LINETABLE:
@@ -3240,6 +3250,107 @@ bool AsmParser::parseDirectiveCVFile() {
   return false;
 }
 
+bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
+                                  StringRef DirectiveName) {
+  SMLoc Loc;
+  return parseTokenLoc(Loc) ||
+         parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
+                                       "' directive") ||
+         check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc,
+               "expected function id within range [0, UINT_MAX)");
+}
+
+bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
+  SMLoc Loc;
+  return parseTokenLoc(Loc) ||
+         parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
+                                       "' directive") ||
+         check(FileNumber < 1, Loc, "file number less than one in '" +
+                                        DirectiveName + "' directive") ||
+         check(!getCVContext().isValidFileNumber(FileNumber), Loc,
+               "unassigned file number in '" + DirectiveName + "' directive");
+}
+
+/// parseDirectiveCVFuncId
+/// ::= .cv_func_id FunctionId
+///
+/// Introduces a function ID that can be used with .cv_loc.
+bool AsmParser::parseDirectiveCVFuncId() {
+  SMLoc FunctionIdLoc = getTok().getLoc();
+  int64_t FunctionId;
+
+  if (parseCVFunctionId(FunctionId, ".cv_func_id") ||
+      parseToken(AsmToken::EndOfStatement,
+                 "unexpected token in '.cv_func_id' directive"))
+    return true;
+
+  if (!getStreamer().EmitCVFuncIdDirective(FunctionId))
+    Error(FunctionIdLoc, "function id already allocated");
+
+  return false;
+}
+
+/// parseDirectiveCVInlineSiteId
+/// ::= .cv_inline_site_id FunctionId
+///         "within" IAFunc
+///         "inlined_at" IAFile IALine [IACol]
+///
+/// Introduces a function ID that can be used with .cv_loc. Includes "inlined
+/// at" source location information for use in the line table of the caller,
+/// whether the caller is a real function or another inlined call site.
+bool AsmParser::parseDirectiveCVInlineSiteId() {
+  SMLoc FunctionIdLoc = getTok().getLoc();
+  int64_t FunctionId;
+  int64_t IAFunc;
+  int64_t IAFile;
+  int64_t IALine;
+  int64_t IACol = 0;
+
+  // FunctionId
+  if (parseCVFunctionId(FunctionId, ".cv_inline_site_id"))
+    return true;
+
+  // "within"
+  if (check((getLexer().isNot(AsmToken::Identifier) ||
+             getTok().getIdentifier() != "within"),
+            "expected 'within' identifier in '.cv_inline_site_id' directive"))
+    return true;
+  Lex();
+
+  // IAFunc
+  if (parseCVFunctionId(IAFunc, ".cv_inline_site_id"))
+    return true;
+
+  // "inlined_at"
+  if (check((getLexer().isNot(AsmToken::Identifier) ||
+             getTok().getIdentifier() != "inlined_at"),
+            "expected 'inlined_at' identifier in '.cv_inline_site_id' "
+            "directive") )
+    return true;
+  Lex();
+
+  // IAFile IALine
+  if (parseCVFileId(IAFile, ".cv_inline_site_id") ||
+      parseIntToken(IALine, "expected line number after 'inlined_at'"))
+    return true;
+
+  // [IACol]
+  if (getLexer().is(AsmToken::Integer)) {
+    IACol = getTok().getIntVal();
+    Lex();
+  }
+
+  if (parseToken(AsmToken::EndOfStatement,
+                 "unexpected token in '.cv_inline_site_id' directive"))
+    return true;
+
+  if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
+                                                 IALine, IACol, FunctionIdLoc))
+    Error(FunctionIdLoc, "function id already allocated");
+
+  return false;
+}
+
 /// parseDirectiveCVLoc
 /// ::= .cv_loc FunctionId FileNumber [LineNumber] [ColumnPos] [prologue_end]
 ///                                [is_stmt VALUE]
@@ -3248,18 +3359,11 @@ bool AsmParser::parseDirectiveCVFile() {
 /// third number is a column position (zero if not specified).  The remaining
 /// optional items are .loc sub-directives.
 bool AsmParser::parseDirectiveCVLoc() {
+  SMLoc DirectiveLoc = getTok().getLoc();
   SMLoc Loc;
   int64_t FunctionId, FileNumber;
-  if (parseTokenLoc(Loc) ||
-      parseIntToken(FunctionId, "unexpected token in '.cv_loc' directive") ||
-      check(FunctionId < 0, Loc,
-            "function id less than zero in '.cv_loc' directive") ||
-      parseTokenLoc(Loc) ||
-      parseIntToken(FileNumber, "expected integer in '.cv_loc' directive") ||
-      check(FileNumber < 1, Loc,
-            "file number less than one in '.cv_loc' directive") ||
-      check(!getCVContext().isValidFileNumber(FileNumber), Loc,
-            "unassigned file number in '.cv_loc' directive"))
+  if (parseCVFunctionId(FunctionId, ".cv_loc") ||
+      parseCVFileId(FileNumber, ".cv_loc"))
     return true;
 
   int64_t LineNumber = 0;
@@ -3307,7 +3411,8 @@ bool AsmParser::parseDirectiveCVLoc() {
   Lex();
 
   getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber,
-                                   ColumnPos, PrologueEnd, IsStmt, StringRef());
+                                   ColumnPos, PrologueEnd, IsStmt, StringRef(),
+                                   DirectiveLoc);
   return false;
 }
 
@@ -3317,10 +3422,7 @@ bool AsmParser::parseDirectiveCVLinetabl
   int64_t FunctionId;
   StringRef FnStartName, FnEndName;
   SMLoc Loc = getTok().getLoc();
-  if (parseIntToken(FunctionId,
-                    "expected Integer in '.cv_linetable' directive") ||
-      check(FunctionId < 0, Loc,
-            "function id less than zero in '.cv_linetable' directive") ||
+  if (parseCVFunctionId(FunctionId, ".cv_linetable") ||
       parseToken(AsmToken::Comma,
                  "unexpected token in '.cv_linetable' directive") ||
       parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc,
@@ -3340,16 +3442,11 @@ bool AsmParser::parseDirectiveCVLinetabl
 
 /// parseDirectiveCVInlineLinetable
 /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
-///          ("contains" SecondaryFunctionId+)?
 bool AsmParser::parseDirectiveCVInlineLinetable() {
   int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
   StringRef FnStartName, FnEndName;
   SMLoc Loc = getTok().getLoc();
-  if (parseIntToken(
-          PrimaryFunctionId,
-          "expected PrimaryFunctionId in '.cv_inline_linetable' directive") ||
-      check(PrimaryFunctionId < 0, Loc,
-            "function id less than zero in '.cv_inline_linetable' directive") ||
+  if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") ||
       parseTokenLoc(Loc) ||
       parseIntToken(
           SourceFileId,
@@ -3368,24 +3465,6 @@ bool AsmParser::parseDirectiveCVInlineLi
                                   "expected identifier in directive"))
     return true;
 
-  SmallVector<unsigned, 8> SecondaryFunctionIds;
-  if (getLexer().is(AsmToken::Identifier)) {
-    if (getTok().getIdentifier() != "contains")
-      return TokError(
-          "unexpected identifier in '.cv_inline_linetable' directive");
-    Lex();
-
-    while (getLexer().isNot(AsmToken::EndOfStatement)) {
-      int64_t SecondaryFunctionId = getTok().getIntVal();
-      if (SecondaryFunctionId < 0)
-        return TokError(
-            "function id less than zero in '.cv_inline_linetable' directive");
-      Lex();
-
-      SecondaryFunctionIds.push_back(SecondaryFunctionId);
-    }
-  }
-
   if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement"))
     return true;
 
@@ -3393,7 +3472,7 @@ bool AsmParser::parseDirectiveCVInlineLi
   MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
   getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
                                                SourceLineNum, FnStartSym,
-                                               FnEndSym, SecondaryFunctionIds);
+                                               FnEndSym);
   return false;
 }
 
@@ -4701,9 +4780,11 @@ void AsmParser::initializeDirectiveKindM
   DirectiveKindMap[".loc"] = DK_LOC;
   DirectiveKindMap[".stabs"] = DK_STABS;
   DirectiveKindMap[".cv_file"] = DK_CV_FILE;
+  DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
   DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
   DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
   DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
+  DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
   DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
   DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
   DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;

Modified: llvm/trunk/lib/MC/MCStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCStreamer.cpp Wed Sep  7 11:15:31 2016
@@ -220,22 +220,54 @@ bool MCStreamer::EmitCVFileDirective(uns
   return getContext().getCVContext().addFile(FileNo, Filename);
 }
 
+bool MCStreamer::EmitCVFuncIdDirective(unsigned FunctionId) {
+  return getContext().getCVContext().recordFunctionId(FunctionId);
+}
+
+bool MCStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
+                                             unsigned IAFunc, unsigned IAFile,
+                                             unsigned IALine, unsigned IACol,
+                                             SMLoc Loc) {
+  if (getContext().getCVContext().getCVFunctionInfo(IAFunc) == nullptr) {
+    getContext().reportError(Loc, "parent function id not introduced by "
+                                  ".cv_func_id or .cv_inline_site_id");
+    return true;
+  }
+
+  return getContext().getCVContext().recordInlinedCallSiteId(
+      FunctionId, IAFunc, IAFile, IALine, IACol);
+}
+
 void MCStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
                                     unsigned Line, unsigned Column,
                                     bool PrologueEnd, bool IsStmt,
-                                    StringRef FileName) {
-  getContext().getCVContext().setCurrentCVLoc(FunctionId, FileNo, Line, Column,
-                                              PrologueEnd, IsStmt);
+                                    StringRef FileName, SMLoc Loc) {
+  CodeViewContext &CVC = getContext().getCVContext();
+  MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FunctionId);
+  if (!FI)
+    return getContext().reportError(
+        Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
+
+  // Track the section
+  if (FI->Section == nullptr)
+    FI->Section = getCurrentSectionOnly();
+  else if (FI->Section != getCurrentSectionOnly())
+    return getContext().reportError(
+        Loc,
+        "all .cv_loc directives for a function must be in the same section");
+
+  CVC.setCurrentCVLoc(FunctionId, FileNo, Line, Column, PrologueEnd, IsStmt);
 }
 
 void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
                                           const MCSymbol *Begin,
                                           const MCSymbol *End) {}
 
-void MCStreamer::EmitCVInlineLinetableDirective(
-    unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
-    const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
-    ArrayRef<unsigned> SecondaryFunctionIds) {}
+void MCStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
+                                                unsigned SourceFileId,
+                                                unsigned SourceLineNum,
+                                                const MCSymbol *FnStartSym,
+                                                const MCSymbol *FnEndSym) {}
 
 void MCStreamer::EmitCVDefRangeDirective(
     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,

Modified: llvm/trunk/test/DebugInfo/COFF/inlining-header.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/inlining-header.ll?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/inlining-header.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/inlining-header.ll Wed Sep  7 11:15:31 2016
@@ -25,13 +25,16 @@
 
 ; ASM: _main:                                  # @main
 ; ASM: Lfunc_begin0:
+; ASM:         .cv_func_id 0
 ; ASM: # BB#0:                                 # %entry
 ; ASM:         .cv_file        1 "D:\\src\\llvm\\build\\t.cpp"
 ; ASM:         .cv_loc 0 1 9 5 is_stmt 0       # t.cpp:9:5
 ; ASM:         incl    "?x@@3HC"
+; ASM:         .cv_inline_site_id 1 within 0 inlined_at 1 10 3
 ; ASM:         .cv_loc 1 1 4 5                 # t.cpp:4:5
 ; ASM:         addl    $2, "?x@@3HC"
 ; ASM:         .cv_file        2 "D:\\src\\llvm\\build\\t.h"
+; ASM:         .cv_inline_site_id 2 within 1 inlined_at 1 5 3
 ; ASM:         .cv_loc 2 2 2 5                 # ./t.h:2:5
 ; ASM:         addl    $3, "?x@@3HC"
 ; ASM:         .cv_loc 1 1 6 5                 # t.cpp:6:5
@@ -61,7 +64,6 @@
 
 ; OBJ: Subsection [
 ; OBJ:   SubSectionType: Symbols (0xF1)
-; OBJ:   SubSectionSize: 0x62
 ; OBJ:   ProcStart {
 ; OBJ:     Kind: S_GPROC32_ID (0x1147)
 ; OBJ:     FunctionType: main (0x1005)
@@ -78,7 +80,8 @@
 ; OBJ:          Inlinee: g (0x1002)
 ; OBJ:          BinaryAnnotations [
 ; OBJ-NEXT:       ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x6, LineOffset: 1}
-; OBJ-NEXT:       ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xE, LineOffset: 2}
+; OBJ-NEXT:       ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1}
+; OBJ-NEXT:       ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1}
 ; OBJ-NEXT:       ChangeCodeLength: 0x7
 ; OBJ-NEXT:     ]
 ; OBJ:        }

Modified: llvm/trunk/test/DebugInfo/COFF/inlining-levels.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/inlining-levels.ll?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/inlining-levels.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/inlining-levels.ll Wed Sep  7 11:15:31 2016
@@ -20,13 +20,13 @@
 ; OBJ:   SubSectionType: Symbols (0xF1)
 ; OBJ:   ProcStart {
 ; OBJ:   InlineSite {
-; OBJ:     Inlinee: h (0x1004)
+; OBJ:     Inlinee: h (0x1002)
 ; OBJ:   }
 ; OBJ:   InlineSite {
 ; OBJ:     Inlinee: g (0x1003)
 ; OBJ:   }
 ; OBJ:   InlineSite {
-; OBJ:     Inlinee: f (0x1002)
+; OBJ:     Inlinee: f (0x1004)
 ; OBJ:   }
 ; OBJ:   InlineSiteEnd {
 ; OBJ:   }

Modified: llvm/trunk/test/DebugInfo/COFF/inlining.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/inlining.ll?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/inlining.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/inlining.ll Wed Sep  7 11:15:31 2016
@@ -21,11 +21,14 @@
 ; 16:   x += 7;
 ; 17: }
 
+; ASM: .cv_func_id 0
 ; ASM: .cv_loc 0 1 13 0 is_stmt 0      # t.cpp:13:0
 ; ASM: .cv_loc 0 1 14 5                # t.cpp:14:5
 ; ASM: addl    $6, "?x@@3HC"
+; ASM: .cv_inline_site_id 1 within 0 inlined_at 1 15 3
 ; ASM: .cv_loc 1 1 9 5                 # t.cpp:9:5
 ; ASM: addl    $4, "?x@@3HC"
+; ASM: .cv_inline_site_id 2 within 1 inlined_at 1 10 3
 ; ASM: .cv_loc 2 1 3 7                 # t.cpp:3:7
 ; ASM: .cv_loc 2 1 4 5                 # t.cpp:4:5
 ; ASM: addl    {{.*}}, "?x@@3HC"
@@ -60,7 +63,7 @@
 ; ASM: .long
 ; ASM: .long
 ; ASM: .long
-; ASM: .cv_inline_linetable 1 1 8 Lfunc_begin0 Lfunc_end0 contains 2
+; ASM: .cv_inline_linetable 1 1 8 Lfunc_begin0 Lfunc_end0
 ; ASM: .short 4429
 ; ASM: .long
 ; ASM: .long
@@ -184,8 +187,9 @@
 ; OBJ:     Inlinee: bar (0x1002)
 ; OBJ:      BinaryAnnotations [
 ; OBJ-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x8, LineOffset: 1}
-; OBJ-NEXT:   ChangeLineOffset: 2
-; OBJ-NEXT:   ChangeCodeOffset: 0x25
+; OBJ-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1}
+; OBJ-NEXT:   ChangeLineOffset: 1
+; OBJ-NEXT:   ChangeCodeOffset: 0x1E
 ; OBJ-NEXT:   ChangeCodeLength: 0x7
 ; OBJ:      ]
 ; OBJ:   }

Modified: llvm/trunk/test/DebugInfo/COFF/local-variables.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/COFF/local-variables.ll?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/COFF/local-variables.ll (original)
+++ llvm/trunk/test/DebugInfo/COFF/local-variables.ll Wed Sep  7 11:15:31 2016
@@ -22,6 +22,7 @@
 ; 17: }
 
 ; ASM: f:                                      # @f
+; ASM:         .cv_func_id 0
 ; ASM:         .cv_file        1 "D:\\src\\llvm\\build\\t.cpp"
 ; ASM:         .cv_loc 0 1 7 0 is_stmt 0       # t.cpp:7:0
 ; ASM: .seh_proc f
@@ -40,6 +41,7 @@
 ; ASM:         .cv_loc 0 1 9 9                 # t.cpp:9:9
 ; ASM:         movl    $42, 40(%rsp)
 ; ASM: [[inline_site1:\.Ltmp.*]]:
+; ASM:         .cv_inline_site_id 1 within 0 inlined_at 1 10 5
 ; ASM:         .cv_loc 1 1 4 7                 # t.cpp:4:7
 ; ASM:         movl    $3, 44(%rsp)
 ; ASM:         leaq    44(%rsp), %rcx
@@ -54,6 +56,7 @@
 ; ASM:         .cv_loc 0 1 13 9                # t.cpp:13:9
 ; ASM:         movl    $42, 36(%rsp)
 ; ASM: [[inline_site2:\.Ltmp.*]]:
+; ASM:         .cv_inline_site_id 2 within 0 inlined_at 1 14 5
 ; ASM:         .cv_loc 2 1 4 7                 # t.cpp:4:7
 ; ASM:         movl    $3, 48(%rsp)
 ; ASM:         leaq    48(%rsp), %rcx

Modified: llvm/trunk/test/MC/COFF/cv-def-range.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-def-range.s?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-def-range.s (original)
+++ llvm/trunk/test/MC/COFF/cv-def-range.s Wed Sep  7 11:15:31 2016
@@ -15,6 +15,7 @@
 _g:                                     # @g
 Lfunc_begin0:
 	.cv_file	1 "\\usr\\local\\google\\home\\majnemer\\llvm\\src\\<stdin>"
+	.cv_func_id 0
 	.cv_loc	0 1 3 0 is_stmt 0       # <stdin>:3:0
 # BB#0:                                 # %entry
 	pushl	%ebp

Modified: llvm/trunk/test/MC/COFF/cv-empty-linetable.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-empty-linetable.s?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-empty-linetable.s (original)
+++ llvm/trunk/test/MC/COFF/cv-empty-linetable.s Wed Sep  7 11:15:31 2016
@@ -16,6 +16,7 @@ _f:
 Lfunc_begin0:
 # BB#0:                                 # %entry
 	.cv_file	1 "cv-empty-linetable.s"
+	.cv_func_id 1
 	.cv_loc	1 1 3 15 is_stmt 0
 	jmp	_g                      # TAILCALL
 Lfunc_end0:

Added: llvm/trunk/test/MC/COFF/cv-errors.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-errors.s?rev=280822&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-errors.s (added)
+++ llvm/trunk/test/MC/COFF/cv-errors.s Wed Sep  7 11:15:31 2016
@@ -0,0 +1,56 @@
+# RUN: not llvm-mc %s -o /dev/null 2>&1 | FileCheck %s
+
+.text
+foo:
+.cv_file a
+# CHECK: error: expected file number in '.cv_file' directive
+# CHECK-NOT: error:
+.cv_file 0 "t.cpp"
+# CHECK: error: file number less than one
+# CHECK-NOT: error:
+.cv_func_id x
+# CHECK: error: expected function id in '.cv_func_id' directive
+# CHECK-NOT: error:
+.cv_func_id -1
+# CHECK: error: expected function id in '.cv_func_id' directive
+# CHECK-NOT: error:
+.cv_func_id 0xFFFFFFFFFFFFFFFF
+# CHECK: error: expected function id within range [0, UINT_MAX)
+# CHECK-NOT: error:
+.cv_inline_site_id x
+# CHECK: error: expected function id in '.cv_inline_site_id' directive
+# CHECK-NOT: error:
+
+.cv_file 1 "t.cpp"
+.cv_func_id 0
+
+.cv_inline_site_id 0 0 0 0 0 0
+# CHECK: error: expected 'within' identifier in '.cv_inline_site_id' directive
+# CHECK-NOT: error:
+
+.cv_inline_site_id 0 within a
+# CHECK: error: expected function id in '.cv_inline_site_id' directive
+# CHECK-NOT: error:
+
+.cv_inline_site_id 0 within 0 x
+# CHECK: error: expected 'inlined_at' identifier in '.cv_inline_site_id' directive
+# CHECK-NOT: error:
+
+.cv_inline_site_id 0 within 0 inlined_at 0 0 0
+# CHECK: error: file number less than one in '.cv_inline_site_id' directive
+# CHECK-NOT: error:
+
+.cv_inline_site_id 0 within 0 inlined_at 10 0 0
+# CHECK: error: unassigned file number in '.cv_inline_site_id' directive
+# CHECK-NOT: error:
+
+.cv_inline_site_id 0 within 0 inlined_at 1 1 1
+# CHECK: error: function id already allocated
+# CHECK-NOT: error:
+
+.cv_inline_site_id 1 within 0 inlined_at 1 1 1
+
+.cv_loc 0 1 1 1 # t.cpp:1:1
+nop
+.cv_loc 1 1 1 1 # t.cpp:1:1
+nop

Modified: llvm/trunk/test/MC/COFF/cv-inline-linetable-infloop.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-inline-linetable-infloop.s?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-inline-linetable-infloop.s (original)
+++ llvm/trunk/test/MC/COFF/cv-inline-linetable-infloop.s Wed Sep  7 11:15:31 2016
@@ -19,6 +19,8 @@
 	.p2align	4, 0x90
 infloop:                                    # @infloop
 .Lfunc_begin1:
+	.cv_func_id 0
+	.cv_inline_site_id 2 within 0 inlined_at 1 1 1
 	.cv_loc	2 1 3 7                 # t.c:3:7
 	jmp	.Lfunc_begin1
 .Lfunc_end1:
@@ -31,6 +33,7 @@ infloop:
 	.globl	afterinfloop
 	.p2align	4, 0x90
 afterinfloop:                                    # @afterinfloop
+	.cv_func_id 3
 	.cv_loc	3 1 13 0                # t.c:13:0
 	retq
 

Added: llvm/trunk/test/MC/COFF/cv-inline-linetable-unlikely.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-inline-linetable-unlikely.s?rev=280822&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-inline-linetable-unlikely.s (added)
+++ llvm/trunk/test/MC/COFF/cv-inline-linetable-unlikely.s Wed Sep  7 11:15:31 2016
@@ -0,0 +1,191 @@
+# RUN: llvm-mc -triple=x86_64-windows -filetype=obj < %s | llvm-readobj -codeview | FileCheck %s
+
+# C source to generate the assembly:
+# volatile int unlikely_cond = 0;
+# extern void __declspec(noreturn) abort();
+# __forceinline void f() {
+#   if (unlikely_cond)
+#     abort();
+# }
+# void g() {
+#   unlikely_cond = 0;
+#   f();
+#   unlikely_cond = 0;
+# }
+
+# This test is interesting because the inlined instructions are discontiguous.
+# LLVM's block layout algorithms will put the 'abort' call last, as it is
+# considered highly unlikely to execute. This is similar to what it does for
+# calls to __asan_report*, for which it is very important to have an accurate
+# stack trace.
+
+# CHECK:    ProcStart {
+# CHECK:      FunctionType: g (0x1003)
+# CHECK:      CodeOffset: g+0x0
+# CHECK:      DisplayName: g
+# CHECK:      LinkageName: g
+# CHECK:    }
+# CHECK:    InlineSite {
+# CHECK:      Inlinee: f (0x1002)
+# CHECK:      BinaryAnnotations [
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xE, LineOffset: 1}
+# CHECK-NEXT:   ChangeCodeLength: 0x9
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xF, LineOffset: 1}
+# CHECK-NEXT:   ChangeCodeLength: 0x7
+# CHECK-NEXT: ]
+
+	.text
+	.globl	g
+g:                                      # @g
+.Lfunc_begin0:
+	.cv_func_id 0
+	.cv_file	1 "C:\\src\\llvm\\build\\t.cpp"
+	.cv_loc	0 1 7 0 is_stmt 0       # t.cpp:7:0
+.seh_proc g
+	subq	$40, %rsp
+	.seh_stackalloc 40
+	.seh_endprologue
+	.cv_loc	0 1 8 17                # t.cpp:8:17
+	movl	$0, unlikely_cond(%rip)
+	.cv_inline_site_id 1 within 0 inlined_at 1 9 3
+	.cv_loc	1 1 4 7                 # t.cpp:4:7
+	cmpl	$0, unlikely_cond(%rip)
+	jne	.LBB0_1
+	.cv_loc	0 1 10 17               # t.cpp:10:17
+	movl	$0, unlikely_cond(%rip)
+	.cv_loc	0 1 11 1                # t.cpp:11:1
+	addq	$40, %rsp
+	retq
+
+.LBB0_1:                                # %if.then.i
+	.cv_loc	1 1 5 5                 # t.cpp:5:5
+	callq	abort
+	ud2
+.Lfunc_end0:
+	.seh_handlerdata
+	.text
+	.seh_endproc
+
+	.bss
+	.globl	unlikely_cond           # @unlikely_cond
+	.p2align	2
+unlikely_cond:
+	.long	0                       # 0x0
+
+	.section	.debug$S,"dr"
+	.p2align	2
+	.long	4                       # Debug section magic
+	.long	246                     # Inlinee lines subsection
+	.long	.Ltmp9-.Ltmp8           # Subsection size
+.Ltmp8:
+	.long	0                       # Inlinee lines signature
+
+                                        # Inlined function f starts at t.cpp:3
+	.long	4098                    # Type index of inlined function
+	.long	0                       # Offset into filechecksum table
+	.long	3                       # Starting line number
+.Ltmp9:
+	.p2align	2
+	.long	241                     # Symbol subsection for g
+	.long	.Ltmp11-.Ltmp10         # Subsection size
+.Ltmp10:
+	.short	.Ltmp13-.Ltmp12         # Record length
+.Ltmp12:
+	.short	4423                    # Record kind: S_GPROC32_ID
+	.long	0                       # PtrParent
+	.long	0                       # PtrEnd
+	.long	0                       # PtrNext
+	.long	.Lfunc_end0-g           # Code size
+	.long	0                       # Offset after prologue
+	.long	0                       # Offset before epilogue
+	.long	4099                    # Function type index
+	.secrel32	g               # Function section relative address
+	.secidx	g                       # Function section index
+	.byte	0                       # Flags
+	.asciz	"g"                     # Function name
+.Ltmp13:
+	.short	.Ltmp15-.Ltmp14         # Record length
+.Ltmp14:
+	.short	4429                    # Record kind: S_INLINESITE
+	.long	0                       # PtrParent
+	.long	0                       # PtrEnd
+	.long	4098                    # Inlinee type index
+	.cv_inline_linetable	1 1 3 .Lfunc_begin0 .Lfunc_end0
+.Ltmp15:
+	.short	2                       # Record length
+	.short	4430                    # Record kind: S_INLINESITE_END
+	.short	2                       # Record length
+	.short	4431                    # Record kind: S_PROC_ID_END
+.Ltmp11:
+	.p2align	2
+	.cv_linetable	0, g, .Lfunc_end0
+	.long	241                     # Symbol subsection for globals
+	.long	.Ltmp17-.Ltmp16         # Subsection size
+.Ltmp16:
+	.short	.Ltmp19-.Ltmp18         # Record length
+.Ltmp18:
+	.short	4365                    # Record kind: S_GDATA32
+	.long	4100                    # Type
+	.secrel32	unlikely_cond   # DataOffset
+	.secidx	unlikely_cond           # Segment
+	.asciz	"unlikely_cond"         # Name
+.Ltmp19:
+.Ltmp17:
+	.p2align	2
+	.cv_filechecksums               # File index to string table offset subsection
+	.cv_stringtable                 # String table
+	.section	.debug$T,"dr"
+	.p2align	2
+	.long	4                       # Debug section magic
+	# ArgList (0x1000) {
+	#   TypeLeafKind: LF_ARGLIST (0x1201)
+	#   NumArgs: 0
+	#   Arguments [
+	#   ]
+	# }
+	.byte	0x06, 0x00, 0x01, 0x12
+	.byte	0x00, 0x00, 0x00, 0x00
+	# Procedure (0x1001) {
+	#   TypeLeafKind: LF_PROCEDURE (0x1008)
+	#   ReturnType: void (0x3)
+	#   CallingConvention: NearC (0x0)
+	#   FunctionOptions [ (0x0)
+	#   ]
+	#   NumParameters: 0
+	#   ArgListType: () (0x1000)
+	# }
+	.byte	0x0e, 0x00, 0x08, 0x10
+	.byte	0x03, 0x00, 0x00, 0x00
+	.byte	0x00, 0x00, 0x00, 0x00
+	.byte	0x00, 0x10, 0x00, 0x00
+	# FuncId (0x1002) {
+	#   TypeLeafKind: LF_FUNC_ID (0x1601)
+	#   ParentScope: 0x0
+	#   FunctionType: void () (0x1001)
+	#   Name: f
+	# }
+	.byte	0x0e, 0x00, 0x01, 0x16
+	.byte	0x00, 0x00, 0x00, 0x00
+	.byte	0x01, 0x10, 0x00, 0x00
+	.byte	0x66, 0x00, 0xf2, 0xf1
+	# FuncId (0x1003) {
+	#   TypeLeafKind: LF_FUNC_ID (0x1601)
+	#   ParentScope: 0x0
+	#   FunctionType: void () (0x1001)
+	#   Name: g
+	# }
+	.byte	0x0e, 0x00, 0x01, 0x16
+	.byte	0x00, 0x00, 0x00, 0x00
+	.byte	0x01, 0x10, 0x00, 0x00
+	.byte	0x67, 0x00, 0xf2, 0xf1
+	# Modifier (0x1004) {
+	#   TypeLeafKind: LF_MODIFIER (0x1001)
+	#   ModifiedType: int (0x74)
+	#   Modifiers [ (0x2)
+	#     Volatile (0x2)
+	#   ]
+	# }
+	.byte	0x0a, 0x00, 0x01, 0x10
+	.byte	0x74, 0x00, 0x00, 0x00
+	.byte	0x02, 0x00, 0xf2, 0xf1
+

Modified: llvm/trunk/test/MC/COFF/cv-inline-linetable-unreachable.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-inline-linetable-unreachable.s?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-inline-linetable-unreachable.s (original)
+++ llvm/trunk/test/MC/COFF/cv-inline-linetable-unreachable.s Wed Sep  7 11:15:31 2016
@@ -15,6 +15,8 @@
 _g:                                     # @g
 Lfunc_begin0:
 	.cv_file	1 "\\usr\\local\\google\\home\\majnemer\\llvm\\src\\<stdin>"
+	.cv_func_id 0
+	.cv_inline_site_id 1 within 0 inlined_at 1 1 1
 	.cv_loc	0 1 7 0 is_stmt 0       # <stdin>:7:0
 # BB#0:                                 # %entry
 	pushl	%ebp

Modified: llvm/trunk/test/MC/COFF/cv-inline-linetable.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-inline-linetable.s?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-inline-linetable.s (original)
+++ llvm/trunk/test/MC/COFF/cv-inline-linetable.s Wed Sep  7 11:15:31 2016
@@ -15,6 +15,9 @@
 "?baz@@YAXXZ":                          # @"\01?baz@@YAXXZ"
 Lfunc_begin0:
 	.cv_file	1 "D:\\src\\llvm\\build\\t.cpp"
+	.cv_func_id 0
+	.cv_inline_site_id 1 within 0 inlined_at 1 15 3
+	.cv_inline_site_id 2 within 1 inlined_at 1 10 3
 	.cv_loc	0 1 13 0 is_stmt 0      # t.cpp:13:0
 # BB#0:                                 # %entry
 	pushl	%eax
@@ -84,16 +87,18 @@ Ltmp3:
 Ltmp4:
 	.short	4429
 	.asciz	"\000\000\000\000\000\000\000\000\003\020\000"
-	.cv_inline_linetable	1 1 9 Lfunc_begin0 Lfunc_end0 contains 2
+	.cv_inline_linetable	1 1 9 Lfunc_begin0 Lfunc_end0
 # CHECK:    InlineSite {
 # CHECK:      PtrParent: 0x0
 # CHECK:      PtrEnd: 0x0
 # CHECK:      Inlinee: bar (0x1003)
 # CHECK:      BinaryAnnotations [
-# CHECK:        ChangeLineOffset: 2
-# CHECK:        ChangeCodeOffset: 0x2D
-# CHECK:        ChangeCodeLength: 0x7
-# CHECK:      ]
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x8, LineOffset: 0}
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1}
+# CHECK-NEXT:   ChangeLineOffset: 1
+# CHECK-NEXT:   ChangeCodeOffset: 0x1E
+# CHECK-NEXT:   ChangeCodeLength: 0x7
+# CHECK-NEXT: ]
 # CHECK:    }
 Ltmp5:
 	.short	Ltmp7-Ltmp6
@@ -106,12 +111,12 @@ Ltmp6:
 # CHECK:      PtrEnd: 0x0
 # CHECK:      Inlinee: foo (0x1004)
 # CHECK:      BinaryAnnotations [
-# CHECK:        ChangeLineOffset: 1
-# CHECK:        ChangeCodeOffset: 0x19
-# CHECK:        ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x6, LineOffset: 1}
-# CHECK:        ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1}
-# CHECK:        ChangeCodeLength: 0x7
-# CHECK:      ]
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xF, LineOffset: 0}
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xA, LineOffset: 1}
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x6, LineOffset: 1}
+# CHECK-NEXT:   ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1}
+# CHECK-NEXT:   ChangeCodeLength: 0x7
+# CHECK-NEXT: ]
 # CHECK:    }
 Ltmp7:
 	.short	2

Added: llvm/trunk/test/MC/COFF/cv-loc-cross-section.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-loc-cross-section.s?rev=280822&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-loc-cross-section.s (added)
+++ llvm/trunk/test/MC/COFF/cv-loc-cross-section.s Wed Sep  7 11:15:31 2016
@@ -0,0 +1,26 @@
+# RUN: not llvm-mc < %s -o /dev/null 2>&1 | FileCheck %s
+
+	.text
+	.global baz
+baz:
+.Lfunc_begin0:
+	.cv_file 1 "t.cpp"
+	.cv_func_id 0
+	.cv_loc 0 1 1 1
+	pushq %rbp
+	movq %rsp, %rbp
+	.cv_loc 0 1 2 1
+
+	.data # Switching sections raises an error.
+
+	incl    x(%rip)
+	.cv_loc 0 1 3 1
+# CHECK: error: all .cv_loc directives for a function must be in the same section
+	popq %rbp
+	retq
+.Lfunc_end0:
+
+	.section	.debug$S,"dr"
+	.cv_linetable 0 .Lfunc_begin0 .Lfunc_end0
+	.short 2   # Record length
+	.short 2   # Record kind: S_INLINESITE_END

Modified: llvm/trunk/test/MC/COFF/cv-loc.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/cv-loc.s?rev=280822&r1=280821&r2=280822&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/cv-loc.s (original)
+++ llvm/trunk/test/MC/COFF/cv-loc.s Wed Sep  7 11:15:31 2016
@@ -7,6 +7,8 @@
 .cv_file 1 "a.c"
 .cv_file 2 "t.inc"
 
+.cv_func_id 0
+
 # Implements this C:
 # void f(volatile int *x) {
 #   ++*x;




More information about the llvm-commits mailing list