[llvm] r343883 - [DebugInfo] Add support for DWARF5 call site-related attributes

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 5 13:37:17 PDT 2018


Author: vedantk
Date: Fri Oct  5 13:37:17 2018
New Revision: 343883

URL: http://llvm.org/viewvc/llvm-project?rev=343883&view=rev
Log:
[DebugInfo] Add support for DWARF5 call site-related attributes

DWARF v5 introduces DW_AT_call_all_calls, a subprogram attribute which
indicates that all calls (both regular and tail) within the subprogram
have call site entries. The information within these call site entries
can be used by a debugger to populate backtraces with synthetic tail
call frames.

Tail calling frames go missing in backtraces because the frame of the
caller is reused by the callee. Call site entries allow a debugger to
reconstruct a sequence of (tail) calls which led from one function to
another. This improves backtrace quality. There are limitations: tail
recursion isn't handled, variables within synthetic frames may not
survive to be inspected, etc. This approach is not novel, see:

  https://gcc.gnu.org/wiki/summit2010?action=AttachFile&do=get&target=jelinek.pdf

This patch adds an IR-level flag (DIFlagAllCallsDescribed) which lowers
to DW_AT_call_all_calls. It adds the minimal amount of DWARF generation
support needed to emit standards-compliant call site entries. For easier
deployment, when the debugger tuning is LLDB, the DWARF requirement is
adjusted to v4.

Testing: Apart from check-{llvm, clang}, I built a stage2 RelWithDebInfo
clang binary. Its dSYM passed verification and grew by 1.4% compared to
the baseline. 151,879 call site entries were added.

rdar://42001377

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

Added:
    llvm/trunk/test/DebugInfo/Generic/callsite-attr-invalid.ll
    llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll
    llvm/trunk/test/tools/llvm-dwarfdump/X86/callsite-invalid.s
Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
    llvm/trunk/include/llvm/IR/DebugInfoFlags.def
    llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h Fri Oct  5 13:37:17 2018
@@ -148,6 +148,8 @@ private:
   ///  - That the root DIE is a unit DIE.
   ///  - If a unit type is provided, that the unit DIE matches the unit type.
   ///  - The DIE ranges.
+  ///  - That call site entries are only nested within subprograms with a
+  ///    DW_AT_call attribute.
   ///
   /// \param Unit      The DWARF Unit to verify.
   ///
@@ -164,6 +166,12 @@ private:
   unsigned verifyUnitSection(const DWARFSection &S,
                              DWARFSectionKind SectionKind);
 
+  /// Verifies that a call site entry is nested within a subprogram with a
+  /// DW_AT_call attribute.
+  ///
+  /// \returns Number of errors that occurred during verification.
+  unsigned verifyDebugInfoCallSite(const DWARFDie &Die);
+
   /// Verify that all Die ranges are valid.
   ///
   /// This function currently checks for:

Modified: llvm/trunk/include/llvm/IR/DebugInfoFlags.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoFlags.def?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoFlags.def (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoFlags.def Fri Oct  5 13:37:17 2018
@@ -50,6 +50,7 @@ HANDLE_DI_FLAG((1 << 25), Thunk)
 HANDLE_DI_FLAG((1 << 26), Trivial)
 HANDLE_DI_FLAG((1 << 27), BigEndian)
 HANDLE_DI_FLAG((1 << 28), LittleEndian)
+HANDLE_DI_FLAG((1 << 29), AllCallsDescribed)
 
 // To avoid needing a dedicated value for IndirectVirtualBase, we use
 // the bitwise or of Virtual and FwdDecl, which does not otherwise
@@ -59,7 +60,7 @@ HANDLE_DI_FLAG((1 << 2) | (1 << 5), Indi
 #ifdef DI_FLAG_LARGEST_NEEDED
 // intended to be used with ADT/BitmaskEnum.h
 // NOTE: always must be equal to largest flag, check this when adding new flag
-HANDLE_DI_FLAG((1 << 28), Largest)
+HANDLE_DI_FLAG((1 << 29), Largest)
 #undef DI_FLAG_LARGEST_NEEDED
 #endif
 

Modified: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfoMetadata.h?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h (original)
+++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h Fri Oct  5 13:37:17 2018
@@ -1736,6 +1736,9 @@ public:
   }
   bool isExplicit() const { return getFlags() & FlagExplicit; }
   bool isPrototyped() const { return getFlags() & FlagPrototyped; }
+  bool areAllCallsDescribed() const {
+    return getFlags() & FlagAllCallsDescribed;
+  }
   bool isMainSubprogram() const { return getFlags() & FlagMainSubprogram; }
 
   /// Check if this is reference-qualified.

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Fri Oct  5 13:37:17 2018
@@ -730,7 +730,8 @@ DIE *DwarfCompileUnit::createScopeChildr
   return ObjectPointer;
 }
 
-void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) {
+DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub,
+                                                   LexicalScope *Scope) {
   DIE &ScopeDIE = updateSubprogramScopeDIE(Sub);
 
   if (Scope) {
@@ -753,6 +754,8 @@ void DwarfCompileUnit::constructSubprogr
       !includeMinimalInlineScopes())
     ScopeDIE.addChild(
         DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters));
+
+  return ScopeDIE;
 }
 
 DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
@@ -807,6 +810,32 @@ void DwarfCompileUnit::constructAbstract
     ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
 }
 
+DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
+                                                 const DISubprogram &CalleeSP,
+                                                 bool IsTail,
+                                                 const MCSymbol *ReturnPC) {
+  // Insert a call site entry DIE within ScopeDIE.
+  DIE &CallSiteDIE =
+      createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr);
+
+  // For the purposes of showing tail call frames in backtraces, a key piece of
+  // information is DW_AT_call_origin, a pointer to the callee DIE.
+  DIE *CalleeDIE = getOrCreateSubprogramDIE(&CalleeSP);
+  assert(CalleeDIE && "Could not create DIE for call site entry origin");
+  addDIEEntry(CallSiteDIE, dwarf::DW_AT_call_origin, *CalleeDIE);
+
+  if (IsTail) {
+    // Attach DW_AT_call_tail_call to tail calls for standards compliance.
+    addFlag(CallSiteDIE, dwarf::DW_AT_call_tail_call);
+  } else {
+    // Attach the return PC to allow the debugger to disambiguate call paths
+    // from one function to another.
+    assert(ReturnPC && "Missing return PC information for a call");
+    addLabelAddress(CallSiteDIE, dwarf::DW_AT_call_return_pc, ReturnPC);
+  }
+  return CallSiteDIE;
+}
+
 DIE *DwarfCompileUnit::constructImportedEntityDIE(
     const DIImportedEntity *Module) {
   DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Fri Oct  5 13:37:17 2018
@@ -203,12 +203,20 @@ public:
                               bool *HasNonScopeChildren = nullptr);
 
   /// Construct a DIE for this subprogram scope.
-  void constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope);
+  DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
+                                   LexicalScope *Scope);
 
   DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);
 
   void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
 
+  /// Construct a call site entry DIE describing a call within \p Scope to a
+  /// callee described by \p CalleeSP. \p IsTail specifies whether the call is
+  /// a tail call. \p ReturnPC must be non-null for non-tail calls and point
+  /// to the PC value after the call returns.
+  DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP,
+                                 bool IsTail, const MCSymbol *ReturnPC);
+
   /// Construct import_module DIE.
   DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Fri Oct  5 13:37:17 2018
@@ -39,6 +39,7 @@
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/Constants.h"
@@ -502,6 +503,63 @@ void DwarfDebug::constructAbstractSubpro
   }
 }
 
+void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
+                                            DwarfCompileUnit &CU, DIE &ScopeDIE,
+                                            const MachineFunction &MF) {
+  // Add a call site-related attribute (DWARF5, Sec. 3.3.1.3). Do this only if
+  // the subprogram is required to have one.
+  if (!SP.areAllCallsDescribed() || !SP.isDefinition())
+    return;
+
+  // Use DW_AT_call_all_calls to express that call site entries are present
+  // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls
+  // because one of its requirements is not met: call site entries for
+  // optimized-out calls are elided.
+  CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls);
+
+  const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+  assert(TII && "TargetInstrInfo not found: cannot label tail calls");
+
+  // Emit call site entries for each call or tail call in the function.
+  for (const MachineBasicBlock &MBB : MF) {
+    for (const MachineInstr &MI : MBB.instrs()) {
+      // Skip instructions which aren't calls. Both calls and tail-calling jump
+      // instructions (e.g TAILJMPd64) are classified correctly here.
+      if (!MI.isCall())
+        continue;
+
+      // TODO: Add support for targets with delay slots (see: beginInstruction).
+      if (MI.hasDelaySlot())
+        return;
+
+      // If this is a direct call, find the callee's subprogram.
+      const MachineOperand &CalleeOp = MI.getOperand(0);
+      if (!CalleeOp.isGlobal())
+        continue;
+      const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
+      if (!CalleeDecl || !CalleeDecl->getSubprogram())
+        continue;
+
+      // TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
+      // TODO: Add support for indirect calls.
+
+      bool IsTail = TII->isTailCall(MI);
+
+      // For tail calls, no return PC information is needed. For regular calls,
+      // the return PC is needed to disambiguate paths in the call graph which
+      // could lead to some target function.
+      const MCSymbol *ReturnPC = IsTail ? nullptr : getLabelAfterInsn(&MI);
+
+      assert((IsTail || ReturnPC) && "Call without return PC information");
+      LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
+                        << CalleeDecl->getName() << (IsTail ? " [tail]" : "")
+                        << "\n");
+      CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(),
+                                   IsTail, ReturnPC);
+    }
+  }
+}
+
 void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const {
   if (!U.hasDwarfPubSections())
     return;
@@ -1376,6 +1434,11 @@ void DwarfDebug::beginInstruction(const
   unsigned LastAsmLine =
       Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
 
+  // Request a label after the call in order to emit AT_return_pc information
+  // in call site entries. TODO: Add support for targets with delay slots.
+  if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot())
+    requestLabelAfterInsn(MI);
+
   if (DL == PrevInstLoc) {
     // If we have an ongoing unspecified location, nothing to do here.
     if (!DL)
@@ -1546,12 +1609,15 @@ void DwarfDebug::endFunctionImpl(const M
   }
 
   ProcessedSPNodes.insert(SP);
-  TheCU.constructSubprogramScopeDIE(SP, FnScope);
+  DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope);
   if (auto *SkelCU = TheCU.getSkeleton())
     if (!LScopes.getAbstractScopesList().empty() &&
         TheCU.getCUNode()->getSplitDebugInlining())
       SkelCU->constructSubprogramScopeDIE(SP, FnScope);
 
+  // Construct call site entries.
+  constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);
+
   // Clear debug info
   // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
   // DbgVariables except those that are also in AbstractVariables (since they

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Fri Oct  5 13:37:17 2018
@@ -424,6 +424,10 @@ class DwarfDebug : public DebugHandlerBa
   /// Construct a DIE for this abstract scope.
   void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
 
+  /// Construct DIEs for call site entries describing the calls in \p MF.
+  void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU,
+                                  DIE &ScopeDIE, const MachineFunction &MF);
+
   template <typename DataT>
   void addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel,
                         StringRef Name, const DIE &Die);

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp Fri Oct  5 13:37:17 2018
@@ -194,6 +194,7 @@ unsigned DWARFVerifier::verifyUnitConten
       dump(Die) << '\n';
       NumUnitErrors++;
     }
+    NumUnitErrors += verifyDebugInfoCallSite(Die);
   }
 
   DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
@@ -223,6 +224,38 @@ unsigned DWARFVerifier::verifyUnitConten
   return NumUnitErrors;
 }
 
+unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
+  if (Die.getTag() != DW_TAG_call_site)
+    return 0;
+
+  DWARFDie Curr = Die.getParent();
+  for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) {
+    if (Curr.getTag() == DW_TAG_inlined_subroutine) {
+      error() << "Call site entry nested within inlined subroutine:";
+      Curr.dump(OS);
+      return 1;
+    }
+  }
+
+  if (!Curr.isValid()) {
+    error() << "Call site entry not nested within a valid subprogram:";
+    Die.dump(OS);
+    return 1;
+  }
+
+  Optional<DWARFFormValue> CallAttr =
+      Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls,
+                 DW_AT_call_all_tail_calls});
+  if (!CallAttr) {
+    error() << "Subprogram with call site entry has no DW_AT_call attribute:";
+    Curr.dump(OS);
+    Die.dump(OS, /*indent*/ 1);
+    return 1;
+  }
+
+  return 0;
+}
+
 unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
   unsigned NumErrors = 0;
   if (Abbrev) {

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Oct  5 13:37:17 2018
@@ -1119,6 +1119,10 @@ void Verifier::visitDISubprogram(const D
       AssertDI(Op && isa<DIType>(Op), "invalid thrown type", &N, ThrownTypes,
                Op);
   }
+
+  if (N.areAllCallsDescribed())
+    AssertDI(N.isDefinition(),
+             "DIFlagAllCallsDescribed must be attached to a definition");
 }
 
 void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) {

Added: llvm/trunk/test/DebugInfo/Generic/callsite-attr-invalid.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/callsite-attr-invalid.ll?rev=343883&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/Generic/callsite-attr-invalid.ll (added)
+++ llvm/trunk/test/DebugInfo/Generic/callsite-attr-invalid.ll Fri Oct  5 13:37:17 2018
@@ -0,0 +1,48 @@
+; RUN: opt -verify < %s 2>&1 | FileCheck %s
+
+; CHECK: DIFlagAllCallsDescribed must be attached to a definition
+; CHECK: warning: ignoring invalid debug info
+
+; Source:
+;   struct A { ~A(); };
+;   void foo() { A x; }
+
+%struct.A = type { i8 }
+
+define void @_Z3foov() !dbg !8 {
+entry:
+  %x = alloca %struct.A, align 1
+  call void @llvm.dbg.declare(metadata %struct.A* %x, metadata !12, metadata !DIExpression()), !dbg !19
+  call void @_ZN1AD1Ev(%struct.A* %x) #3, !dbg !20
+  ret void, !dbg !20
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+declare void @_ZN1AD1Ev(%struct.A*)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "-", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{i32 7, !"PIC Level", i32 2}
+!7 = !{!"clang version 8.0.0 "}
+!8 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !9, file: !9, line: 1, type: !10, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!9 = !DIFile(filename: "<stdin>", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA")
+!10 = !DISubroutineType(types: !11)
+!11 = !{null}
+!12 = !DILocalVariable(name: "x", scope: !8, file: !9, line: 1, type: !13)
+!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !9, line: 1, size: 8, flags: DIFlagTypePassByReference, elements: !14, identifier: "_ZTS1A")
+!14 = !{!15}
+!15 = !DISubprogram(name: "~A", scope: !13, file: !9, line: 1, type: !16, isLocal: false, isDefinition: false, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: false)
+!16 = !DISubroutineType(types: !17)
+!17 = !{null, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!19 = !DILocation(line: 1, column: 36, scope: !8)
+!20 = !DILocation(line: 1, column: 39, scope: !8)

Added: llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll?rev=343883&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll Fri Oct  5 13:37:17 2018
@@ -0,0 +1,133 @@
+; $ clang++ -S -emit-llvm -o - -gdwarf-5 -o - -O1 tail2.cc
+; volatile int sink;
+; void __attribute__((noinline)) bat() { sink++; }
+; void __attribute__((noinline)) bar() { sink++; }
+; void __attribute__((noinline)) foo() {
+;   bar(); bat();
+;   bar(); bat();
+; }
+; int __attribute__((disable_tail_calls)) main() { foo(); }
+
+; REQUIRES: object-emission
+; RUN: %llc_dwarf < %s -o - | FileCheck %s -check-prefix=ASM
+; RUN: %llc_dwarf < %s -filetype=obj -o %t.o
+; RUN: llvm-dwarfdump %t.o -o - | FileCheck %s -check-prefix=OBJ -implicit-check-not=DW_TAG_call_site
+; RUN: llvm-dwarfdump -verify %t.o 2>&1 | FileCheck %s -check-prefix=VERIFY
+; RUN: llvm-dwarfdump -statistics %t.o | FileCheck %s -check-prefix=STATS
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis -o /dev/null
+
+; VERIFY: No errors.
+; STATS: "call site entries":5
+
+ at sink = global i32 0, align 4, !dbg !0
+
+; ASM: DW_TAG_subprogram
+; ASM:   DW_AT_call_all_calls
+; OBJ: [[bat_sp:.*]]: DW_TAG_subprogram
+; OBJ:   DW_AT_call_all_calls (true)
+; OBJ:   DW_AT_name ("bat")
+define void @_Z3batv() !dbg !13 {
+entry:
+  %0 = load volatile i32, i32* @sink, align 4, !dbg !16, !tbaa !17
+  %inc = add nsw i32 %0, 1, !dbg !16
+  store volatile i32 %inc, i32* @sink, align 4, !dbg !16, !tbaa !17
+  ret void, !dbg !21
+}
+
+; ASM: DW_TAG_subprogram
+; ASM:   DW_AT_call_all_calls
+; OBJ: [[bar_sp:.*]]: DW_TAG_subprogram
+; OBJ:   DW_AT_call_all_calls (true)
+; OBJ:   DW_AT_name ("bar")
+define void @_Z3barv() !dbg !22 {
+entry:
+  %0 = load volatile i32, i32* @sink, align 4, !dbg !23, !tbaa !17
+  %inc = add nsw i32 %0, 1, !dbg !23
+  store volatile i32 %inc, i32* @sink, align 4, !dbg !23, !tbaa !17
+  ret void, !dbg !24
+}
+
+; ASM: DW_TAG_subprogram
+; ASM:   DW_AT_call_all_calls
+; OBJ: [[foo_sp:.*]]: DW_TAG_subprogram
+; OBJ:   DW_AT_call_all_calls (true)
+; OBJ:   DW_AT_name ("foo")
+; OBJ:   DW_TAG_call_site
+; OBJ:     DW_AT_call_origin ([[bar_sp]])
+; OBJ:     DW_AT_call_return_pc ({{[0x]+}}26)
+; OBJ:   DW_TAG_call_site
+; OBJ:     DW_AT_call_origin ([[bat_sp]])
+; OBJ:     DW_AT_call_return_pc ({{[0x]+}}2b)
+; OBJ:   DW_TAG_call_site
+; OBJ:     DW_AT_call_origin ([[bar_sp]])
+; OBJ:     DW_AT_call_return_pc ({{[0x]+}}30)
+; OBJ:   DW_TAG_call_site
+; OBJ:     DW_AT_call_origin ([[bat_sp]])
+; OBJ:     DW_AT_call_tail_call
+define void @_Z3foov() !dbg !25 {
+entry:
+  tail call void @_Z3barv(), !dbg !26
+  tail call void @_Z3batv(), !dbg !27
+  tail call void @_Z3barv(), !dbg !26
+  tail call void @_Z3batv(), !dbg !27
+  ret void, !dbg !28
+}
+
+; ASM: DW_TAG_subprogram
+; ASM: DW_AT_call_all_calls
+; OBJ: DW_TAG_subprogram
+; OBJ: DW_AT_call_all_calls (true)
+; OBJ: DW_AT_name ("main")
+; OBJ:   DW_TAG_call_site
+; OBJ:     DW_AT_call_origin ([[foo_sp]])
+; OBJ:     DW_AT_call_return_pc ({{[0x]+}}46)
+define i32 @main() !dbg !29 {
+entry:
+  call void @_Z3foov(), !dbg !32
+
+  %indirect_target = load void ()*, void ()** undef
+  call void %indirect_target()
+
+  call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
+
+  ret i32 0, !dbg !33
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!8, !9, !10, !11}
+!llvm.ident = !{!12}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "sink", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "/Users/vsk/src/llvm.org-tailcall/tail2.cc", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA", checksumkind: CSK_MD5, checksum: "3b61952c21b7f657ddb7c0ad44cf5529")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{i32 2, !"Dwarf Version", i32 5}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{i32 1, !"wchar_size", i32 4}
+!11 = !{i32 7, !"PIC Level", i32 2}
+!12 = !{!"clang version 7.0.0 "}
+!13 = distinct !DISubprogram(name: "bat", linkageName: "_Z3batv", scope: !3, file: !3, line: 2, type: !14, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+!14 = !DISubroutineType(types: !15)
+!15 = !{null}
+!16 = !DILocation(line: 2, column: 44, scope: !13)
+!17 = !{!18, !18, i64 0}
+!18 = !{!"int", !19, i64 0}
+!19 = !{!"omnipotent char", !20, i64 0}
+!20 = !{!"Simple C++ TBAA"}
+!21 = !DILocation(line: 2, column: 48, scope: !13)
+!22 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 3, type: !14, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+!23 = !DILocation(line: 3, column: 44, scope: !22)
+!24 = !DILocation(line: 3, column: 48, scope: !22)
+!25 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+!26 = !DILocation(line: 5, column: 3, scope: !25)
+!27 = !DILocation(line: 6, column: 3, scope: !25)
+!28 = !DILocation(line: 7, column: 1, scope: !25)
+!29 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 8, type: !30, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+!30 = !DISubroutineType(types: !31)
+!31 = !{!7}
+!32 = !DILocation(line: 8, column: 50, scope: !29)
+!33 = !DILocation(line: 8, column: 57, scope: !29)

Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/callsite-invalid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/callsite-invalid.s?rev=343883&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/callsite-invalid.s (added)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/callsite-invalid.s Fri Oct  5 13:37:17 2018
@@ -0,0 +1,376 @@
+# RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o %t.o
+# RUN: not llvm-dwarfdump -verify %t.o 2>&1 | FileCheck %s
+
+# CHECK: error: Subprogram with call site entry has no DW_AT_call attribute:
+# CHECK: DW_TAG_subprogram
+# CHECK:   DW_AT_name ("main")
+# CHECK: DW_TAG_call_site
+# CHECK:   DW_AT_call_origin
+# CHECK: Errors detected.
+
+# Source:
+## define void @foo() !dbg !25 {
+##   ret void, !dbg !28
+## }
+##
+## define i32 @main() !dbg !29 {
+##   call void @foo(), !dbg !32
+##   ret i32 0, !dbg !33
+## }
+##
+## !llvm.dbg.cu = !{!2}
+## !llvm.module.flags = !{!8, !9, !10, !11}
+## !llvm.ident = !{!12}
+##
+## !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+## !1 = distinct !DIGlobalVariable(name: "sink", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
+## !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+## !3 = !DIFile(filename: "/Users/vsk/src/llvm.org-tailcall/tail2.cc", directory: "/Users/vsk/src/builds/llvm-project-tailcall-RA", checksumkind: CSK_MD5, checksum: "3b61952c21b7f657ddb7c0ad44cf5529")
+## !4 = !{}
+## !5 = !{!0}
+## !6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
+## !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+## !8 = !{i32 2, !"Dwarf Version", i32 5}
+## !9 = !{i32 2, !"Debug Info Version", i32 3}
+## !10 = !{i32 1, !"wchar_size", i32 4}
+## !11 = !{i32 7, !"PIC Level", i32 2}
+## !12 = !{!"clang version 7.0.0 "}
+## !13 = distinct !DISubprogram(name: "bat", linkageName: "_Z3batv", scope: !3, file: !3, line: 2, type: !14, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+## !14 = !DISubroutineType(types: !15)
+## !15 = !{null}
+## !16 = !DILocation(line: 2, column: 44, scope: !13)
+## !17 = !{!18, !18, i64 0}
+## !18 = !{!"int", !19, i64 0}
+## !19 = !{!"omnipotent char", !20, i64 0}
+## !20 = !{!"Simple C++ TBAA"}
+## !21 = !DILocation(line: 2, column: 48, scope: !13)
+## !22 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 3, type: !14, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+## !23 = !DILocation(line: 3, column: 44, scope: !22)
+## !24 = !DILocation(line: 3, column: 48, scope: !22)
+## !25 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 4, type: !14, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+## !26 = !DILocation(line: 5, column: 3, scope: !25)
+## !27 = !DILocation(line: 6, column: 3, scope: !25)
+## !28 = !DILocation(line: 7, column: 1, scope: !25)
+## !29 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 8, type: !30, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, isOptimized: true, unit: !2, retainedNodes: !4)
+## !30 = !DISubroutineType(types: !31)
+## !31 = !{!7}
+## !32 = !DILocation(line: 8, column: 50, scope: !29)
+## !33 = !DILocation(line: 8, column: 57, scope: !29)
+
+        .section        __TEXT,__text,regular,pure_instructions
+        .globl  _foo                    ## -- Begin function foo
+_foo:                                   ## @foo
+Lfunc_begin0:
+        .cfi_startproc
+## %bb.0:
+        retq
+Ltmp0:
+Lfunc_end0:
+        .cfi_endproc
+                                        ## -- End function
+        .globl  _main                   ## -- Begin function main
+_main:                                  ## @main
+Lfunc_begin1:
+        .cfi_startproc
+## %bb.0:
+        pushq   %rax
+        .cfi_def_cfa_offset 16
+Ltmp1:
+        callq   _foo
+        xorl    %eax, %eax
+        popq    %rcx
+        retq
+Ltmp2:
+Lfunc_end1:
+        .cfi_endproc
+                                        ## -- End function
+        .section        __DWARF,__debug_str_offs,regular,debug
+Lsection_str_off:
+        .long   36
+        .short  5
+        .short  0
+Lstr_offsets_base0:
+        .section        __DWARF,__debug_str,regular,debug
+Linfo_string:
+        .asciz  "clang version 7.0.0 "  ## string offset=0
+        .asciz  "/Users/vsk/src/llvm.org-tailcall/tail2.cc" ## string offset=21
+        .asciz  "/Users/vsk/src/builds/llvm-project-tailcall-RA" ## string offset=63
+        .asciz  "sink"                  ## string offset=110
+        .asciz  "int"                   ## string offset=115
+        .asciz  "foo"                   ## string offset=119
+        .asciz  "_Z3foov"               ## string offset=123
+        .asciz  "main"                  ## string offset=131
+        .section        __DWARF,__debug_str_offs,regular,debug
+        .long   0
+        .long   21
+        .long   63
+        .long   110
+        .long   115
+        .long   119
+        .long   123
+        .long   131
+        .section        __DWARF,__debug_abbrev,regular,debug
+Lsection_abbrev:
+        .byte   1                       ## Abbreviation Code
+        .byte   17                      ## DW_TAG_compile_unit
+        .byte   1                       ## DW_CHILDREN_yes
+        .byte   37                      ## DW_AT_producer
+        .byte   37                      ## DW_FORM_strx1
+        .byte   19                      ## DW_AT_language
+        .byte   5                       ## DW_FORM_data2
+        .byte   3                       ## DW_AT_name
+        .byte   37                      ## DW_FORM_strx1
+        .byte   114                     ## DW_AT_str_offsets_base
+        .byte   23                      ## DW_FORM_sec_offset
+        .byte   16                      ## DW_AT_stmt_list
+        .byte   23                      ## DW_FORM_sec_offset
+        .byte   27                      ## DW_AT_comp_dir
+        .byte   37                      ## DW_FORM_strx1
+        .ascii  "\341\177"              ## DW_AT_APPLE_optimized
+        .byte   25                      ## DW_FORM_flag_present
+        .byte   17                      ## DW_AT_low_pc
+        .byte   1                       ## DW_FORM_addr
+        .byte   18                      ## DW_AT_high_pc
+        .byte   6                       ## DW_FORM_data4
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   2                       ## Abbreviation Code
+        .byte   52                      ## DW_TAG_variable
+        .byte   0                       ## DW_CHILDREN_no
+        .byte   3                       ## DW_AT_name
+        .byte   37                      ## DW_FORM_strx1
+        .byte   73                      ## DW_AT_type
+        .byte   19                      ## DW_FORM_ref4
+        .byte   63                      ## DW_AT_external
+        .byte   25                      ## DW_FORM_flag_present
+        .byte   58                      ## DW_AT_decl_file
+        .byte   11                      ## DW_FORM_data1
+        .byte   59                      ## DW_AT_decl_line
+        .byte   11                      ## DW_FORM_data1
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   3                       ## Abbreviation Code
+        .byte   53                      ## DW_TAG_volatile_type
+        .byte   0                       ## DW_CHILDREN_no
+        .byte   73                      ## DW_AT_type
+        .byte   19                      ## DW_FORM_ref4
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   4                       ## Abbreviation Code
+        .byte   36                      ## DW_TAG_base_type
+        .byte   0                       ## DW_CHILDREN_no
+        .byte   3                       ## DW_AT_name
+        .byte   37                      ## DW_FORM_strx1
+        .byte   62                      ## DW_AT_encoding
+        .byte   11                      ## DW_FORM_data1
+        .byte   11                      ## DW_AT_byte_size
+        .byte   11                      ## DW_FORM_data1
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   5                       ## Abbreviation Code
+        .byte   46                      ## DW_TAG_subprogram
+        .byte   0                       ## DW_CHILDREN_no
+        .byte   17                      ## DW_AT_low_pc
+        .byte   1                       ## DW_FORM_addr
+        .byte   18                      ## DW_AT_high_pc
+        .byte   6                       ## DW_FORM_data4
+        .ascii  "\347\177"              ## DW_AT_APPLE_omit_frame_ptr
+        .byte   25                      ## DW_FORM_flag_present
+        .byte   64                      ## DW_AT_frame_base
+        .byte   24                      ## DW_FORM_exprloc
+##        .byte   122                     ## DW_AT_call_all_calls
+##        .byte   25                      ## DW_FORM_flag_present
+        .byte   110                     ## DW_AT_linkage_name
+        .byte   37                      ## DW_FORM_strx1
+        .byte   3                       ## DW_AT_name
+        .byte   37                      ## DW_FORM_strx1
+        .byte   58                      ## DW_AT_decl_file
+        .byte   11                      ## DW_FORM_data1
+        .byte   59                      ## DW_AT_decl_line
+        .byte   11                      ## DW_FORM_data1
+        .byte   63                      ## DW_AT_external
+        .byte   25                      ## DW_FORM_flag_present
+        .ascii  "\341\177"              ## DW_AT_APPLE_optimized
+        .byte   25                      ## DW_FORM_flag_present
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   6                       ## Abbreviation Code
+        .byte   46                      ## DW_TAG_subprogram
+        .byte   1                       ## DW_CHILDREN_yes
+        .byte   17                      ## DW_AT_low_pc
+        .byte   1                       ## DW_FORM_addr
+        .byte   18                      ## DW_AT_high_pc
+        .byte   6                       ## DW_FORM_data4
+        .ascii  "\347\177"              ## DW_AT_APPLE_omit_frame_ptr
+        .byte   25                      ## DW_FORM_flag_present
+        .byte   64                      ## DW_AT_frame_base
+        .byte   24                      ## DW_FORM_exprloc
+##        .byte   122                     ## DW_AT_call_all_calls
+##        .byte   25                      ## DW_FORM_flag_present
+        .byte   3                       ## DW_AT_name
+        .byte   37                      ## DW_FORM_strx1
+        .byte   58                      ## DW_AT_decl_file
+        .byte   11                      ## DW_FORM_data1
+        .byte   59                      ## DW_AT_decl_line
+        .byte   11                      ## DW_FORM_data1
+        .byte   73                      ## DW_AT_type
+        .byte   19                      ## DW_FORM_ref4
+        .byte   63                      ## DW_AT_external
+        .byte   25                      ## DW_FORM_flag_present
+        .ascii  "\341\177"              ## DW_AT_APPLE_optimized
+        .byte   25                      ## DW_FORM_flag_present
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   7                       ## Abbreviation Code
+        .byte   72                      ## DW_TAG_call_site
+        .byte   0                       ## DW_CHILDREN_no
+        .byte   127                     ## DW_AT_call_origin
+        .byte   19                      ## DW_FORM_ref4
+        .byte   0                       ## EOM(1)
+        .byte   0                       ## EOM(2)
+        .byte   0                       ## EOM(3)
+        .section        __DWARF,__debug_info,regular,debug
+Lsection_info:
+Lcu_begin0:
+        .long   99                      ## Length of Unit
+        .short  5                       ## DWARF version number
+        .byte   1                       ## DWARF Unit Type
+        .byte   8                       ## Address Size (in bytes)
+.set Lset0, Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
+        .long   Lset0
+        .byte   1                       ## Abbrev [1] 0xc:0x5b DW_TAG_compile_unit
+        .byte   0                       ## DW_AT_producer
+        .short  4                       ## DW_AT_language
+        .byte   1                       ## DW_AT_name
+.set Lset1, Lstr_offsets_base0-Lsection_str_off ## DW_AT_str_offsets_base
+        .long   Lset1
+.set Lset2, Lline_table_start0-Lsection_line ## DW_AT_stmt_list
+        .long   Lset2
+        .byte   2                       ## DW_AT_comp_dir
+                                        ## DW_AT_APPLE_optimized
+        .quad   Lfunc_begin0            ## DW_AT_low_pc
+.set Lset3, Lfunc_end1-Lfunc_begin0     ## DW_AT_high_pc
+        .long   Lset3
+        .byte   2                       ## Abbrev [2] 0x26:0x8 DW_TAG_variable
+        .byte   3                       ## DW_AT_name
+        .long   46                      ## DW_AT_type
+                                        ## DW_AT_external
+        .byte   1                       ## DW_AT_decl_file
+        .byte   1                       ## DW_AT_decl_line
+        .byte   3                       ## Abbrev [3] 0x2e:0x5 DW_TAG_volatile_type
+        .long   51                      ## DW_AT_type
+        .byte   4                       ## Abbrev [4] 0x33:0x4 DW_TAG_base_type
+        .byte   4                       ## DW_AT_name
+        .byte   5                       ## DW_AT_encoding
+        .byte   4                       ## DW_AT_byte_size
+        .byte   5                       ## Abbrev [5] 0x37:0x13 DW_TAG_subprogram
+        .quad   Lfunc_begin0            ## DW_AT_low_pc
+.set Lset4, Lfunc_end0-Lfunc_begin0     ## DW_AT_high_pc
+        .long   Lset4
+                                        ## DW_AT_APPLE_omit_frame_ptr
+        .byte   1                       ## DW_AT_frame_base
+        .byte   87
+                                        ## DW_AT_call_all_calls
+        .byte   6                       ## DW_AT_linkage_name
+        .byte   5                       ## DW_AT_name
+        .byte   1                       ## DW_AT_decl_file
+        .byte   4                       ## DW_AT_decl_line
+                                        ## DW_AT_external
+                                        ## DW_AT_APPLE_optimized
+        .byte   6                       ## Abbrev [6] 0x4a:0x1c DW_TAG_subprogram
+        .quad   Lfunc_begin1            ## DW_AT_low_pc
+.set Lset5, Lfunc_end1-Lfunc_begin1     ## DW_AT_high_pc
+        .long   Lset5
+                                        ## DW_AT_APPLE_omit_frame_ptr
+        .byte   1                       ## DW_AT_frame_base
+        .byte   87
+                                        ## DW_AT_call_all_calls
+        .byte   7                       ## DW_AT_name
+        .byte   1                       ## DW_AT_decl_file
+        .byte   8                       ## DW_AT_decl_line
+        .long   51                      ## DW_AT_type
+                                        ## DW_AT_external
+                                        ## DW_AT_APPLE_optimized
+        .byte   7                       ## Abbrev [7] 0x60:0x5 DW_TAG_call_site
+        .long   55                      ## DW_AT_call_origin
+        .byte   0                       ## End Of Children Mark
+        .byte   0                       ## End Of Children Mark
+        .section        __DWARF,__debug_macinfo,regular,debug
+Ldebug_macinfo:
+        .byte   0                       ## End Of Macro List Mark
+        .section        __DWARF,__debug_names,regular,debug
+Ldebug_names_begin:
+.set Lset6, Lnames_end0-Lnames_start0   ## Header: unit length
+        .long   Lset6
+Lnames_start0:
+        .short  5                       ## Header: version
+        .short  0                       ## Header: padding
+        .long   1                       ## Header: compilation unit count
+        .long   0                       ## Header: local type unit count
+        .long   0                       ## Header: foreign type unit count
+        .long   4                       ## Header: bucket count
+        .long   4                       ## Header: name count
+.set Lset7, Lnames_abbrev_end0-Lnames_abbrev_start0 ## Header: abbreviation table size
+        .long   Lset7
+        .long   8                       ## Header: augmentation string size
+        .ascii  "LLVM0700"              ## Header: augmentation string
+.set Lset8, Lcu_begin0-Lsection_info    ## Compilation unit 0
+        .long   Lset8
+        .long   1                       ## Bucket 0
+        .long   2                       ## Bucket 1
+        .long   3                       ## Bucket 2
+        .long   4                       ## Bucket 3
+        .long   193495088               ## Hash in Bucket 0
+        .long   193491849               ## Hash in Bucket 1
+        .long   2090499946              ## Hash in Bucket 2
+        .long   -1257882357             ## Hash in Bucket 3
+        .long   115                     ## String in Bucket 0: int
+        .long   119                     ## String in Bucket 1: foo
+        .long   131                     ## String in Bucket 2: main
+        .long   123                     ## String in Bucket 3: _Z3foov
+.set Lset9, Lnames3-Lnames_entries0     ## Offset in Bucket 0
+        .long   Lset9
+.set Lset10, Lnames0-Lnames_entries0    ## Offset in Bucket 1
+        .long   Lset10
+.set Lset11, Lnames1-Lnames_entries0    ## Offset in Bucket 2
+        .long   Lset11
+.set Lset12, Lnames2-Lnames_entries0    ## Offset in Bucket 3
+        .long   Lset12
+Lnames_abbrev_start0:
+        .byte   46                      ## Abbrev code
+        .byte   46                      ## DW_TAG_subprogram
+        .byte   3                       ## DW_IDX_die_offset
+        .byte   19                      ## DW_FORM_ref4
+        .byte   0                       ## End of abbrev
+        .byte   0                       ## End of abbrev
+        .byte   36                      ## Abbrev code
+        .byte   36                      ## DW_TAG_base_type
+        .byte   3                       ## DW_IDX_die_offset
+        .byte   19                      ## DW_FORM_ref4
+        .byte   0                       ## End of abbrev
+        .byte   0                       ## End of abbrev
+        .byte   0                       ## End of abbrev list
+Lnames_abbrev_end0:
+Lnames_entries0:
+Lnames3:
+        .byte   36                      ## Abbreviation code
+        .long   51                      ## DW_IDX_die_offset
+        .long   0                       ## End of list: int
+Lnames0:
+        .byte   46                      ## Abbreviation code
+        .long   55                      ## DW_IDX_die_offset
+        .long   0                       ## End of list: foo
+Lnames1:
+        .byte   46                      ## Abbreviation code
+        .long   74                      ## DW_IDX_die_offset
+        .long   0                       ## End of list: main
+Lnames2:
+        .byte   46                      ## Abbreviation code
+        .long   55                      ## DW_IDX_die_offset
+        .long   0                       ## End of list: _Z3foov
+Lnames_end0:
+
+.subsections_via_symbols
+        .section        __DWARF,__debug_line,regular,debug
+Lsection_line:
+Lline_table_start0:

Modified: llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp?rev=343883&r1=343882&r2=343883&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp (original)
+++ llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp Fri Oct  5 13:37:17 2018
@@ -32,6 +32,8 @@ struct GlobalStats {
   /// Total number of PC range bytes in each variable's enclosing scope,
   /// starting from the first definition of the variable.
   unsigned ScopeBytesFromFirstDefinition = 0;
+  /// Total number of call site entries (DW_TAG_call_site).
+  unsigned CallSiteEntries = 0;
 };
 
 /// Extract the low pc from a Die.
@@ -57,6 +59,11 @@ static void collectStatsForDie(DWARFDie
   uint64_t BytesCovered = 0;
   uint64_t OffsetToFirstDefinition = 0;
 
+  if (Die.getTag() == dwarf::DW_TAG_call_site) {
+    GlobalStats.CallSiteEntries++;
+    return;
+  }
+
   if (Die.getTag() != dwarf::DW_TAG_formal_parameter &&
       Die.getTag() != dwarf::DW_TAG_variable &&
       Die.getTag() != dwarf::DW_TAG_member) {
@@ -260,6 +267,7 @@ bool collectStatsForObjectFile(ObjectFil
   printDatum(OS, "unique source variables", VarUnique);
   printDatum(OS, "source variables", VarTotal);
   printDatum(OS, "variables with location", VarWithLoc);
+  printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
   printDatum(OS, "scope bytes total",
              GlobalStats.ScopeBytesFromFirstDefinition);
   printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);




More information about the llvm-commits mailing list