[llvm] r365467 - [DwarfDebug] Dump call site debug info

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 9 04:33:56 PDT 2019


Author: djtodoro
Date: Tue Jul  9 04:33:56 2019
New Revision: 365467

URL: http://llvm.org/viewvc/llvm-project?rev=365467&view=rev
Log:
[DwarfDebug] Dump call site debug info

Dump the DWARF information about call sites and call site parameters into
debug info sections.

The patch also provides an interface for the interpretation of instructions
that could load values of a call site parameters in order to generate DWARF
about the call site parameters.

([13/13] Introduce the debug entry values.)

Co-authored-by: Ananth Sowda <asowda at cisco.com>
Co-authored-by: Nikola Prica <nikola.prica at rt-rk.com>
Co-authored-by: Ivan Baev <ibaev at cisco.com>

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

Added:
    llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir
    llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
    llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir
    llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h
    llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.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/CodeGen/AsmPrinter/DwarfExpression.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
    llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp
    llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp
    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
    llvm/trunk/lib/Target/X86/X86InstrInfo.h
    llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll
    llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Tue Jul  9 04:33:56 2019
@@ -4755,6 +4755,9 @@ The current supported opcode vocabulary
   ``DW_OP_entry_value`` may also appear after the ``AsmPrinter`` pass when
   a call site parameter value (``DW_AT_call_site_parameter_value``)
   is represented as entry value of the parameter.
+- ``DW_OP_reg`` (or ``DW_OP_regx``) represents a physical register location.
+  The opcode is only generated by the ``AsmPrinter`` pass to describe
+  call site parameter value which requires an expression over two registers.
 
 DWARF specifies three kinds of simple location descriptions: Register, memory,
 and implicit location descriptions.  Note that a location description is

Modified: llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetInstrInfo.h Tue Jul  9 04:33:56 2019
@@ -60,6 +60,8 @@ class TargetSubtargetInfo;
 
 template <class T> class SmallVectorImpl;
 
+using ParamLoadedValue = std::pair<const MachineOperand*, DIExpression*>;
+
 //---------------------------------------------------------------------------
 ///
 /// TargetInstrInfo - Interface to description of machine instruction set
@@ -1691,6 +1693,10 @@ public:
     return false;
   }
 
+  /// Produce RHS description of parameter's loading instruction \p MI.
+  virtual Optional<ParamLoadedValue>
+  describeLoadedValue(const MachineInstr &MI) const;
+
 private:
   unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
   unsigned CatchRetOpcode;

Modified: llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetRegisterInfo.h Tue Jul  9 04:33:56 2019
@@ -531,9 +531,7 @@ public:
   /// prior to a call and is guaranteed to be restored (also by the caller)
   /// after the call.
   virtual bool isCallerPreservedPhysReg(unsigned PhysReg,
-                                        const MachineFunction &MF) const {
-    return false;
-  }
+                                        const MachineFunction &MF) const;
 
   /// Prior to adding the live-out mask to a stackmap or patchpoint
   /// instruction, provide the target the opportunity to adjust it (mainly to

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Jul  9 04:33:56 2019
@@ -890,32 +890,106 @@ void DwarfCompileUnit::constructAbstract
     ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
 }
 
+dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUCallSiteTag(dwarf::Tag Tag) {
+  bool ApplyGNUExtensions = DD->getDwarfVersion() == 4 && DD->tuneForGDB();
+  if (!ApplyGNUExtensions)
+    return Tag;
+  switch(Tag) {
+  case dwarf::DW_TAG_call_site:
+    return dwarf::DW_TAG_GNU_call_site;
+  case dwarf::DW_TAG_call_site_parameter:
+    return dwarf::DW_TAG_GNU_call_site_parameter;
+  default:
+    llvm_unreachable("unhandled call site tag");
+  }
+}
+
+dwarf::Attribute DwarfCompileUnit::getDwarf5OrGNUCallSiteAttr(dwarf::Attribute Attr) {
+  bool ApplyGNUExtensions = DD->getDwarfVersion() == 4 && DD->tuneForGDB();
+  if (!ApplyGNUExtensions)
+    return Attr;
+  switch(Attr) {
+  case dwarf::DW_AT_call_all_calls:
+    return dwarf::DW_AT_GNU_all_call_sites;
+  case dwarf::DW_AT_call_target:
+    return dwarf::DW_AT_GNU_call_site_target;
+  case dwarf::DW_AT_call_origin:
+    return dwarf::DW_AT_abstract_origin;
+  case dwarf::DW_AT_call_pc:
+    return dwarf::DW_AT_low_pc;
+  case dwarf::DW_AT_call_value:
+    return dwarf::DW_AT_GNU_call_site_value;
+  case dwarf::DW_AT_call_tail_call:
+    return dwarf::DW_AT_GNU_tail_call;
+  default:
+    llvm_unreachable("unhandled call site attribute");
+  }
+}
+
 DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
-                                                 const DISubprogram &CalleeSP,
+                                                 const DISubprogram *CalleeSP,
                                                  bool IsTail,
-                                                 const MCExpr *PCOffset) {
+                                                 const MCSymbol *PCAddr,
+                                                 const MCExpr *PCOffset,
+                                                 unsigned CallReg) {
   // Insert a call site entry DIE within ScopeDIE.
   DIE &CallSiteDIE =
-      createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr);
+      createAndAddDIE(getDwarf5OrGNUCallSiteTag(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 (CallReg) {
+    // Indirect call.
+    addAddress(CallSiteDIE, getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_target),
+               MachineLocation(CallReg));
+  } else {
+    DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
+    assert(CalleeDIE && "Could not create DIE for call site entry origin");
+    addDIEEntry(CallSiteDIE, getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_origin),
+                *CalleeDIE);
+  }
 
-  if (IsTail) {
+  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.
+    addFlag(CallSiteDIE, getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_tail_call));
+
+  // Attach the return PC to allow the debugger to disambiguate call paths
+  // from one function to another.
+  if (DD->getDwarfVersion() == 4 && DD->tuneForGDB()) {
+    assert(PCAddr && "Missing PC information for a call");
+    addLabelAddress(CallSiteDIE, dwarf::DW_AT_low_pc, PCAddr);
+  } else if (!IsTail || DD->tuneForGDB()) {
     assert(PCOffset && "Missing return PC information for a call");
     addAddressExpr(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCOffset);
   }
+
   return CallSiteDIE;
 }
 
+void DwarfCompileUnit::constructCallSiteParmEntryDIEs(
+    DIE &CallSiteDIE, SmallVector<DbgCallSiteParam, 4> &Params) {
+  for (auto &Param : Params) {
+    unsigned Register = Param.getRegister();
+    auto CallSiteDieParam =
+        DIE::get(DIEValueAllocator,
+                 getDwarf5OrGNUCallSiteTag(dwarf::DW_TAG_call_site_parameter));
+    insertDIE(CallSiteDieParam);
+    addAddress(*CallSiteDieParam, dwarf::DW_AT_location,
+               MachineLocation(Register));
+
+    DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+    DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+    DwarfExpr.setCallSiteParamValueFlag();
+
+    DwarfDebug::emitDebugLocValue(*Asm, nullptr, Param.getValue(), DwarfExpr);
+
+    addBlock(*CallSiteDieParam,
+             getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_value),
+             DwarfExpr.finalize());
+
+    CallSiteDIE.addChild(CallSiteDieParam);
+  }
+}
+
 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=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Tue Jul  9 04:33:56 2019
@@ -227,12 +227,22 @@ public:
 
   void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
 
+  dwarf::Tag getDwarf5OrGNUCallSiteTag(dwarf::Tag Tag);
+  dwarf::Attribute getDwarf5OrGNUCallSiteAttr(dwarf::Attribute Attr);
+
   /// 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 PCOffset must be non-zero for non-tail calls or be the
-  /// function-local offset to PC value after the call instruction.
-  DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP,
-                                 bool IsTail, const MCExpr *PCOffset);
+  /// a tail call. \p PCAddr (used for GDB + DWARF 4 tuning) points to
+  /// the PC value after the call instruction. \p PCOffset (used for
+  /// cases other than GDB + DWARF 4 tuning) must be non-zero for non-tail calls
+  /// (in the case of non-gdb tuning) or be the function-local offset to PC value
+  /// after the call instruction. \p CallReg is a register location
+  /// for an indirect call.
+  DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP,
+                                 bool IsTail, const MCSymbol *PCAddr,
+                                 const MCExpr *PCOffset, unsigned CallReg);
+  void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE,
+                                      SmallVector<DbgCallSiteParam, 4> &Params);
 
   /// 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=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Jul  9 04:33:56 2019
@@ -26,6 +26,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -39,6 +40,7 @@
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
@@ -83,6 +85,8 @@ using namespace llvm;
 
 #define DEBUG_TYPE "dwarfdebug"
 
+STATISTIC(NumCSParams, "Number of dbg call site params created");
+
 static cl::opt<bool>
 DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
                          cl::desc("Disable debug info printing"));
@@ -551,6 +555,123 @@ void DwarfDebug::constructAbstractSubpro
   }
 }
 
+/// Try to interpret values loaded into registers that forward parameters
+/// for \p CallMI. Store parameters with interpreted value into \p Params.
+static void collectCallSiteParameters(const MachineInstr *CallMI,
+                                      ParamSet &Params) {
+  auto *MF = CallMI->getMF();
+  auto CalleesMap = MF->getCallSitesInfo();
+  auto CallFwdRegsInfo = CalleesMap.find(CallMI);
+
+  // There is no information for the call instruction.
+  if (CallFwdRegsInfo == CalleesMap.end())
+    return;
+
+  auto *MBB = CallMI->getParent();
+  const auto &TRI = MF->getSubtarget().getRegisterInfo();
+  const auto &TII = MF->getSubtarget().getInstrInfo();
+  const auto &TLI = MF->getSubtarget().getTargetLowering();
+
+  // Skip the call instruction.
+  auto I = std::next(CallMI->getReverseIterator());
+
+  DenseSet<unsigned> ArgsRegsForProcess;
+  for (auto ArgReg : CallFwdRegsInfo->second)
+    ArgsRegsForProcess.insert(ArgReg.Reg);
+
+  // If we did not find loading a value into forwarding registers
+  // that means we can try generating 'DW_OP_entry_value' for the argument
+  // if a call is within entry MBB.
+  DenseMap<unsigned, unsigned> RegsForEntryValues;
+  bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin();
+
+  // Return true if it is an instruction over a parameter's forwarding
+  // register that clobbers it.
+  auto shouldInterpret = [&](const MachineInstr &MI) -> unsigned {
+    if (MI.isDebugInstr())
+      return 0;
+    // If a MI clobbers a forwarding reg try to interpret
+    // a value loaded into the reg.
+    for (const MachineOperand &MO : MI.operands()) {
+      if (MO.isReg() && MO.isDef() && MO.getReg() &&
+          TRI->isPhysicalRegister(MO.getReg())) {
+        for (auto FwdReg : ArgsRegsForProcess)
+          if (TRI->regsOverlap(FwdReg, MO.getReg()))
+            return FwdReg;
+      }
+    }
+
+    return 0;
+  };
+
+  auto finishCallSiteParam = [&](DbgValueLoc &DbgLocVal,
+                                 unsigned &Reg) {
+    unsigned FwdReg = Reg;
+    if (ShouldTryEmitEntryVals && RegsForEntryValues.count(Reg))
+      FwdReg = RegsForEntryValues[Reg];
+    DbgCallSiteParam CSParm(FwdReg, DbgLocVal);
+    Params.push_back(CSParm);
+    NumCSParams++;
+  };
+
+  // Search for a loading value in forwaring registers.
+  while (I != MBB->rend()) {
+    // If the next instruction is a call we can not
+    // interpret parameter's forwarding registers or
+    // we finished interpretation of all parameters.
+    if (I->isCall())
+      return;
+
+    if (ArgsRegsForProcess.empty())
+      return;
+
+    if (unsigned Reg = shouldInterpret(*I)) {
+      ArgsRegsForProcess.erase(Reg);
+      const MachineOperand *Op;
+      DIExpression *Expr;
+      if (auto ParamValue = TII->describeLoadedValue(*I)) {
+        Op = ParamValue->first;
+        Expr = ParamValue->second;
+        if (Op->isImm()) {
+          unsigned Val = Op->getImm();
+          DbgValueLoc DbgLocVal(Expr, Val);
+          finishCallSiteParam(DbgLocVal, Reg);
+        } else if (Op->isReg()) {
+          unsigned RegLoc = Op->getReg();
+          unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
+          unsigned FP = TRI->getFrameRegister(*MF);
+          bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP);
+          if (TRI->isCallerPreservedPhysReg(RegLoc, *MF) || IsSPorFP) {
+            DbgValueLoc DbgLocVal(
+                Expr, MachineLocation(RegLoc, IsSPorFP));
+            finishCallSiteParam(DbgLocVal, Reg);
+          } else if (ShouldTryEmitEntryVals) {
+            ArgsRegsForProcess.insert(RegLoc);
+            RegsForEntryValues[RegLoc] = Reg;
+          }
+        }
+      }
+    }
+
+    ++I;
+  }
+
+  // Emit call site parameter's value as entry value.
+  if (ShouldTryEmitEntryVals) {
+    DIExpression *EntryExpr = DIExpression::get(MF->getFunction().getContext(),
+                                                {dwarf::DW_OP_entry_value, 1});
+    for (auto RegEntry : ArgsRegsForProcess) {
+      unsigned FwdReg = RegsForEntryValues.count(RegEntry)
+                            ? RegsForEntryValues[RegEntry]
+                            : RegEntry;
+      DbgValueLoc DbgLocVal(EntryExpr, MachineLocation(RegEntry));
+      DbgCallSiteParam CSParm(FwdReg, DbgLocVal);
+      Params.push_back(CSParm);
+      NumCSParams++;
+    }
+  }
+}
+
 void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
                                             DwarfCompileUnit &CU, DIE &ScopeDIE,
                                             const MachineFunction &MF) {
@@ -563,10 +684,13 @@ void DwarfDebug::constructCallSiteEntryD
   // 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);
+  CU.addFlag(ScopeDIE,
+             CU.getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_all_calls));
 
   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
   assert(TII && "TargetInstrInfo not found: cannot label tail calls");
+  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+  bool ApplyGNUExtensions = getDwarfVersion() == 4 && tuneForGDB();
 
   // Emit call site entries for each call or tail call in the function.
   for (const MachineBasicBlock &MBB : MF) {
@@ -581,30 +705,65 @@ void DwarfDebug::constructCallSiteEntryD
         return;
 
       // If this is a direct call, find the callee's subprogram.
+      // In the case of an indirect call find the register that holds
+      // the callee.
       const MachineOperand &CalleeOp = MI.getOperand(0);
-      if (!CalleeOp.isGlobal())
-        continue;
-      const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
-      if (!CalleeDecl || !CalleeDecl->getSubprogram())
+      if (!CalleeOp.isGlobal() && !CalleeOp.isReg())
         continue;
 
+      unsigned CallReg = 0;
+      const DISubprogram *CalleeSP = nullptr;
+      const Function *CalleeDecl = nullptr;
+      if (CalleeOp.isReg()) {
+        CallReg = CalleeOp.getReg();
+        if (!CallReg)
+          continue;
+      } else {
+        CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
+        if (!CalleeDecl || !CalleeDecl->getSubprogram())
+          continue;
+        CalleeSP = CalleeDecl->getSubprogram();
+      }
+
       // 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.
+      // For tail calls, for non-gdb tuning, no return PC information is needed.
+      // For regular calls (and tail calls in GDB tuning), the return PC
+      // is needed to disambiguate paths in the call graph which could lead to
+      // some target function.
       const MCExpr *PCOffset =
-          IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI);
+          (IsTail && !tuneForGDB()) ? nullptr
+                                    : getFunctionLocalOffsetAfterInsn(&MI);
+
+      // Address of a call-like instruction for a normal call or a jump-like
+      // instruction for a tail call. This is needed for GDB + DWARF 4 tuning.
+      const MCSymbol *PCAddr =
+          ApplyGNUExtensions ? const_cast<MCSymbol*>(getLabelAfterInsn(&MI))
+                             : nullptr;
+
+      assert((IsTail || PCOffset || PCAddr) &&
+             "Call without return PC information");
 
-      assert((IsTail || PCOffset) && "Call without return PC information");
       LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
-                        << CalleeDecl->getName() << (IsTail ? " [tail]" : "")
+                        << (CalleeDecl ? CalleeDecl->getName()
+                                       : StringRef(TRI->getName(CallReg)))
+                        << (IsTail ? " [IsTail]" : "")
                         << "\n");
-      CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(),
-                                   IsTail, PCOffset);
+
+      DIE &CallSiteDIE =
+            CU.constructCallSiteEntryDIE(ScopeDIE, CalleeSP, IsTail, PCAddr,
+                                         PCOffset, CallReg);
+
+      // For now only GDB supports call site parameter debug info.
+      if (Asm->TM.Options.EnableDebugEntryValues &&
+          tuneForGDB()) {
+        ParamSet Params;
+        // Try to interpret values of call site parameters.
+        collectCallSiteParameters(&MI, Params);
+        CU.constructCallSiteParmEntryDIEs(CallSiteDIE, Params);
+      }
     }
   }
 }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Tue Jul  9 04:33:56 2019
@@ -254,6 +254,22 @@ public:
   }
 };
 
+/// Used for tracking debug info about call site parameters.
+class DbgCallSiteParam {
+private:
+  unsigned Register;
+  DbgValueLoc Value;
+public:
+  DbgCallSiteParam(unsigned Reg, DbgValueLoc Val)
+      : Register(Reg), Value(Val) {}
+
+  unsigned getRegister() { return Register; }
+  DbgValueLoc getValue() { return Value; }
+};
+
+/// Collection used for storing debug call site parameters.
+using ParamSet = SmallVector<DbgCallSiteParam, 4>;
+
 /// Helper used to pair up a symbol and its DWARF compile unit.
 struct SymbolCU {
   SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp Tue Jul  9 04:33:56 2019
@@ -241,15 +241,20 @@ bool DwarfExpression::addMachineRegExpre
     return false;
   }
 
-  // Handle simple register locations.
-  if (!isMemoryLocation() && !HasComplexExpression) {
+  // Handle simple register locations. If we are supposed to
+  // emit a call site parameter expression and if that expression
+  // is just a register location, emit it with addBReg and offset 0,
+  // because we should emit a DWARF expression representing a value,
+  // rather than a location.
+  if (!isMemoryLocation() && !HasComplexExpression &&
+      (!isParameterValue() || isEntryValue())) {
     for (auto &Reg : DwarfRegs) {
       if (Reg.DwarfRegNo >= 0)
         addReg(Reg.DwarfRegNo, Reg.Comment);
       addOpPiece(Reg.Size);
     }
 
-    if (isEntryValue() && DwarfVersion >= 4)
+    if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4)
       emitOp(dwarf::DW_OP_stack_value);
 
     DwarfRegs.clear();
@@ -340,7 +345,16 @@ void DwarfExpression::addExpression(DIEx
 
   while (ExprCursor) {
     auto Op = ExprCursor.take();
-    switch (Op->getOp()) {
+    uint64_t OpNum = Op->getOp();
+    if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
+      if (isParameterValue())
+        addBReg(OpNum - dwarf::DW_OP_reg0, 0);
+      else
+        emitOp(OpNum);
+      continue;
+    }
+
+    switch (OpNum) {
     case dwarf::DW_OP_LLVM_fragment: {
       unsigned SizeInBits = Op->getArg(1);
       unsigned FragmentOffset = Op->getArg(0);
@@ -389,7 +403,7 @@ void DwarfExpression::addExpression(DIEx
     case dwarf::DW_OP_lit0:
     case dwarf::DW_OP_not:
     case dwarf::DW_OP_dup:
-      emitOp(Op->getOp());
+      emitOp(OpNum);
       break;
     case dwarf::DW_OP_deref:
       assert(!isRegisterLocation());
@@ -458,12 +472,22 @@ void DwarfExpression::addExpression(DIEx
     case dwarf::DW_OP_LLVM_tag_offset:
       TagOffset = Op->getArg(0);
       break;
+    case dwarf::DW_OP_regx:
+      if (isParameterValue()) {
+        emitOp(dwarf::DW_OP_bregx);
+        emitUnsigned(Op->getArg(0));
+        emitSigned(Op->getArg(1));
+      } else {
+        emitOp(dwarf::DW_OP_regx);
+        emitUnsigned(Op->getArg(0));
+      }
+      break;
     default:
       llvm_unreachable("unhandled opcode found in expression");
     }
   }
 
-  if (isImplicitLocation())
+  if (isImplicitLocation() && !isParameterValue())
     // Turn this into an implicit location description.
     addStackValue();
 }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Tue Jul  9 04:33:56 2019
@@ -120,7 +120,7 @@ protected:
   enum { Unknown = 0, Register, Memory, Implicit };
 
   /// The flags of location description being produced.
-  enum { EntryValue = 1 };
+  enum { EntryValue = 1, CallSiteParamValue };
 
   unsigned LocationKind : 3;
   unsigned LocationFlags : 2;
@@ -147,6 +147,10 @@ public:
     return LocationFlags & EntryValue;
   }
 
+  bool isParameterValue() {
+    return LocationFlags & CallSiteParamValue;
+  }
+
   Optional<uint8_t> TagOffset;
 
 protected:
@@ -264,6 +268,11 @@ public:
     LocationFlags |= EntryValue;
   }
 
+  /// Lock this down to become a call site parameter location.
+  void setCallSiteParamValueFlag() {
+    LocationFlags |= CallSiteParamValue;
+  }
+
   /// Emit a machine register location. As an optimization this may also consume
   /// the prefix of a DwarfExpression if a more efficient representation for
   /// combining the register location and the first operation exists.

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Tue Jul  9 04:33:56 2019
@@ -205,6 +205,10 @@ void DwarfUnit::insertDIE(const DINode *
   MDNodeToDieMap.insert(std::make_pair(Desc, D));
 }
 
+void DwarfUnit::insertDIE(DIE *D) {
+  MDNodeToDieMap.insert(std::make_pair(nullptr, D));
+}
+
 void DwarfUnit::addFlag(DIE &Die, dwarf::Attribute Attribute) {
   if (DD->getDwarfVersion() >= 4)
     Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_flag_present,

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h Tue Jul  9 04:33:56 2019
@@ -127,6 +127,8 @@ public:
   /// the mappings are kept in DwarfDebug.
   void insertDIE(const DINode *Desc, DIE *D);
 
+  void insertDIE(DIE *D);
+
   /// Add a flag that is true to the DIE.
   void addFlag(DIE &Die, dwarf::Attribute Attribute);
 

Modified: llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetInstrInfo.cpp Tue Jul  9 04:33:56 2019
@@ -23,6 +23,7 @@
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSchedule.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCInstrItineraries.h"
 #include "llvm/Support/CommandLine.h"
@@ -1120,6 +1121,45 @@ bool TargetInstrInfo::hasLowDefLatency(c
   return (DefCycle != -1 && DefCycle <= 1);
 }
 
+Optional<ParamLoadedValue>
+TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+  const MachineOperand *Op = nullptr;
+  DIExpression *Expr = nullptr;
+
+  const MachineOperand *SrcRegOp, *DestRegOp;
+  const MachineFunction *MF = MI.getMF();
+  if (isCopyInstr(MI, SrcRegOp, DestRegOp)) {
+    Expr = DIExpression::get(MF->getFunction().getContext(), {});
+    Op = SrcRegOp;
+    return ParamLoadedValue(Op, Expr);
+  } else if (MI.isMoveImmediate()) {
+    Expr = DIExpression::get(MF->getFunction().getContext(), {});
+    Op = &MI.getOperand(1);
+    return ParamLoadedValue(Op, Expr);
+  } else if (MI.hasOneMemOperand()) {
+    int64_t Offset;
+    const auto &TRI = MF->getSubtarget().getRegisterInfo();
+    const auto &TII = MF->getSubtarget().getInstrInfo();
+    const MachineOperand *BaseOp;
+    if (!TII->getMemOperandWithOffset(MI, BaseOp, Offset, TRI))
+      return None;
+    unsigned CastedOffset = static_cast<unsigned>(Offset);
+    if (Offset > 0)
+      Expr = DIExpression::get(
+          MF->getFunction().getContext(),
+          {dwarf::DW_OP_plus_uconst, CastedOffset, dwarf::DW_OP_deref});
+    else
+      Expr = DIExpression::get(MF->getFunction().getContext(),
+                               {dwarf::DW_OP_constu, -CastedOffset,
+                                dwarf::DW_OP_minus, dwarf::DW_OP_deref});
+
+    Op = BaseOp;
+    return ParamLoadedValue(Op, Expr);
+  }
+
+  return None;
+}
+
 /// Both DefMI and UseMI must be valid.  By default, call directly to the
 /// itinerary. This may be overriden by the target.
 int TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,

Modified: llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp Tue Jul  9 04:33:56 2019
@@ -433,6 +433,20 @@ TargetRegisterInfo::getRegAllocationHint
   return false;
 }
 
+bool
+TargetRegisterInfo::isCallerPreservedPhysReg(unsigned PhysReg,
+                                             const MachineFunction &MF) const {
+  if (PhysReg == 0)
+    return false;
+  const uint32_t *callerPreservedRegs =
+      getCallPreservedMask(MF, MF.getFunction().getCallingConv());
+  if (callerPreservedRegs) {
+    assert(isPhysicalRegister(PhysReg) && "Expected physical register");
+    return (callerPreservedRegs[PhysReg / 32] >> PhysReg % 32) & 1;
+  }
+  return false;
+}
+
 bool TargetRegisterInfo::canRealignStack(const MachineFunction &MF) const {
   return !MF.getFunction().hasFnAttribute("no-realign-stack");
 }

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Tue Jul  9 04:33:56 2019
@@ -733,6 +733,7 @@ bool DWARFAttribute::mayHaveLocationDesc
   case DW_AT_call_data_value:
   // Extensions.
   case DW_AT_GNU_call_site_value:
+  case DW_AT_GNU_call_site_target:
     return true;
   default:
     return false;

Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Tue Jul  9 04:33:56 2019
@@ -833,10 +833,12 @@ unsigned DIExpression::ExprOperand::getS
   case dwarf::DW_OP_LLVM_fragment:
     return 3;
   case dwarf::DW_OP_constu:
+  case dwarf::DW_OP_consts:
   case dwarf::DW_OP_deref_size:
   case dwarf::DW_OP_plus_uconst:
   case dwarf::DW_OP_LLVM_tag_offset:
   case dwarf::DW_OP_entry_value:
+  case dwarf::DW_OP_regx:
     return 2;
   default:
     return 1;
@@ -849,8 +851,12 @@ bool DIExpression::isValid() const {
     if (I->get() + I->getSize() > E->get())
       return false;
 
+    uint64_t Op = I->getOp();
+    if (Op >= dwarf::DW_OP_reg0 && Op <= dwarf::DW_OP_reg31)
+      continue;
+
     // Check that the operand is valid.
-    switch (I->getOp()) {
+    switch (Op) {
     default:
       return false;
     case dwarf::DW_OP_LLVM_fragment:
@@ -905,6 +911,7 @@ bool DIExpression::isValid() const {
     case dwarf::DW_OP_lit0:
     case dwarf::DW_OP_not:
     case dwarf::DW_OP_dup:
+    case dwarf::DW_OP_regx:
       break;
     }
   }

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Jul  9 04:33:56 2019
@@ -30,7 +30,7 @@
 #include "llvm/CodeGen/StackMaps.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
-#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
@@ -7318,6 +7318,98 @@ bool X86InstrInfo::isAssociativeAndCommu
   }
 }
 
+Optional<ParamLoadedValue>
+X86InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+  const MachineOperand *Op = nullptr;
+  DIExpression *Expr = nullptr;
+
+  switch (MI.getOpcode()) {
+  case X86::LEA32r:
+  case X86::LEA64r:
+  case X86::LEA64_32r: {
+    // Operand 4 could be global address. For now we do not support
+    // such situation.
+    if (!MI.getOperand(4).isImm() || !MI.getOperand(2).isImm())
+      return None;
+
+    const MachineOperand &Op1 = MI.getOperand(1);
+    const MachineOperand &Op2 = MI.getOperand(3);
+    const TargetRegisterInfo *TRI = &getRegisterInfo();
+    assert(Op2.isReg() &&
+           (Op2.getReg() == X86::NoRegister ||
+            TargetRegisterInfo::isPhysicalRegister(Op2.getReg())));
+
+    // Omit situations like:
+    // %rsi = lea %rsi, 4, ...
+    if ((Op1.isReg() && Op1.getReg() == MI.getOperand(0).getReg()) ||
+        Op2.getReg() == MI.getOperand(0).getReg())
+      return None;
+    else if ((Op1.isReg() && Op1.getReg() != X86::NoRegister &&
+              TRI->regsOverlap(Op1.getReg(), MI.getOperand(0).getReg())) ||
+             (Op2.getReg() != X86::NoRegister &&
+              TRI->regsOverlap(Op2.getReg(), MI.getOperand(0).getReg())))
+      return None;
+
+    int64_t Coef = MI.getOperand(2).getImm();
+    int64_t Offset = MI.getOperand(4).getImm();
+    SmallVector<uint64_t, 8> Elements;
+
+    if ((Op1.isReg() && Op1.getReg() != X86::NoRegister)) {
+      Op = &Op1;
+    } else if (Op1.isFI())
+      Op = &Op1;
+
+    if (Op && Op->isReg() && Op->getReg() == Op2.getReg() && Coef > 0) {
+      Elements.push_back(dwarf::DW_OP_constu);
+      Elements.push_back(Coef + 1);
+      Elements.push_back(dwarf::DW_OP_mul);
+    } else {
+      if (Op && Op2.getReg() != X86::NoRegister) {
+        int dwarfReg = TRI->getDwarfRegNum(Op2.getReg(), false);
+        if (dwarfReg < 0)
+          return None;
+        else if (dwarfReg < 32)
+          Elements.push_back(dwarf::DW_OP_reg0 + dwarfReg);
+        else {
+          Elements.push_back(dwarf::DW_OP_regx);
+          Elements.push_back(dwarfReg);
+        }
+      } else if (!Op) {
+        assert(Op2.getReg() != X86::NoRegister);
+        Op = &Op2;
+      }
+
+      if (Coef > 1) {
+        assert(Op2.getReg() != X86::NoRegister);
+        Elements.push_back(dwarf::DW_OP_constu);
+        Elements.push_back(Coef);
+        Elements.push_back(dwarf::DW_OP_mul);
+      }
+
+      if (((Op1.isReg() && Op1.getReg() != X86::NoRegister) || Op1.isFI()) &&
+          Op2.getReg() != X86::NoRegister) {
+        Elements.push_back(dwarf::DW_OP_plus);
+      }
+    }
+
+    if (Offset < 0) {
+      Elements.push_back(dwarf::DW_OP_constu);
+      Elements.push_back(-Offset);
+      Elements.push_back(dwarf::DW_OP_minus);
+    } else if (Offset > 0) {
+      Elements.push_back(dwarf::DW_OP_constu);
+      Elements.push_back(Offset);
+      Elements.push_back(dwarf::DW_OP_plus);
+    }
+
+    Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), Elements);
+    return ParamLoadedValue(Op, Expr);;
+  }
+  default:
+    return TargetInstrInfo::describeLoadedValue(MI);
+  }
+}
+
 /// This is an architecture-specific helper function of reassociateOps.
 /// Set special operand attributes for new instructions after reassociation.
 void X86InstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1,

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Tue Jul  9 04:33:56 2019
@@ -527,6 +527,9 @@ public:
 #define GET_INSTRINFO_HELPER_DECLS
 #include "X86GenInstrInfo.inc"
 
+  Optional<ParamLoadedValue>
+  describeLoadedValue(const MachineInstr &MI) const override;
+
 protected:
   /// Commutes the operands in the given instruction by changing the operands
   /// order and/or changing the instruction's opcode and/or the immediate value

Added: llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir?rev=365467&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-interpretation.mir Tue Jul  9 04:33:56 2019
@@ -0,0 +1,200 @@
+# RUN: llc -debug-entry-values -start-after=machineverifier -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
+#
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT:   DW_AT_abstract_origin {{.*}} "foo"
+# CHECK-NEXT:   DW_AT_low_pc
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg2 RCX)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg1 RDX)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_fbreg +8)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg5 RDI)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_GNU_entry_value(DW_OP_reg4 RSI))
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT:   DW_AT_abstract_origin {{.*}}"foo"
+# CHECK-NEXT:   DW_AT_low_pc
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg2 RCX)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_fbreg +8, DW_OP_deref)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg4 RSI)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_lit4)
+# CHECK-NOT: DW_TAG_GNU_call_site_parameter
+#
+# Check that call site interpretation analysis can interpret instructions such
+# as move immediate, register to register moves, stack loading and LEA
+# instructions. Last negative check should verify that we are not producing
+# interpretation for RDX register since its loaded value is call clobberable.
+# Also check that we are generating proper call site debug entities.
+--- |
+  ; ModuleID = 'dbgcall-site-interpretation.c'
+  source_filename = "dbgcall-site-interpretation.c"
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+  
+  ; Function Attrs: nounwind uwtable
+  define dso_local i32 @baa(i32 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) local_unnamed_addr !dbg !9 {
+  entry:
+    %arg3.addr = alloca i32, align 4
+    %local2 = alloca i32, align 4
+    call void @llvm.dbg.value(metadata i32 %arg1, metadata !14, metadata !DIExpression()), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %arg2, metadata !15, metadata !DIExpression()), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %arg3, metadata !16, metadata !DIExpression()), !dbg !21
+    store i32 %arg3, i32* %arg3.addr, align 4
+    call void @llvm.dbg.value(metadata i32 %arg4, metadata !17, metadata !DIExpression()), !dbg !21
+    %0 = bitcast i32* %local2 to i8*, !dbg !21
+    call void @llvm.dbg.value(metadata i32* %arg3.addr, metadata !16, metadata !DIExpression(DW_OP_deref)), !dbg !21
+    %call = call i32 @foo(i32 %arg1, i32 %arg2, i32* nonnull %arg3.addr, i32 %arg4), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !21
+    %cmp = icmp sgt i32 %arg1, %arg2, !dbg !21
+    %1 = load i32, i32* %arg3.addr, align 4, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %1, metadata !16, metadata !DIExpression()), !dbg !21
+    %add = add nsw i32 %1, %arg1, !dbg !21
+    %add1 = add nsw i32 %arg4, %arg2, !dbg !21
+    %local1.0 = select i1 %cmp, i32 %add, i32 %add1, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %local1.0, metadata !18, metadata !DIExpression()), !dbg !21
+    %rem = srem i32 %1, %arg1, !dbg !21
+    %tobool = icmp eq i32 %rem, 0, !dbg !21
+    %mul = mul nsw i32 %1, %arg1, !dbg !21
+    %add3 = add nsw i32 %1, %arg4, !dbg !21
+    %storemerge = select i1 %tobool, i32 %mul, i32 %add3, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %storemerge, metadata !19, metadata !DIExpression()), !dbg !21
+    store i32 %storemerge, i32* %local2, align 4, !dbg !21
+    %cmp6 = icmp slt i32 %storemerge, %arg4, !dbg !21
+    %local3.0.v = select i1 %cmp6, i32 %local1.0, i32 %arg1, !dbg !21
+    %local3.0 = mul nsw i32 %local3.0.v, %storemerge, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %local3.0, metadata !20, metadata !DIExpression()), !dbg !21
+    call void @llvm.dbg.value(metadata i32* %local2, metadata !19, metadata !DIExpression(DW_OP_deref)), !dbg !21
+    %call12 = call i32 @foo(i32 %local1.0, i32 4, i32* nonnull %local2, i32 %local3.0), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %call12, metadata !14, metadata !DIExpression()), !dbg !21
+    %add13 = add nsw i32 %call12, 4, !dbg !21
+    ret i32 %add13, !dbg !21
+  }
+  
+  declare !dbg !4 dso_local i32 @foo(i32, i32, i32*, i32) local_unnamed_addr
+  
+  ; Function Attrs: nounwind readnone speculatable
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!5, !6, !7}
+  !llvm.ident = !{!8}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "dbgcall-site-interpretation.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !{i32 2, !"Dwarf Version", i32 4}
+  !6 = !{i32 2, !"Debug Info Version", i32 3}
+  !7 = !{i32 1, !"wchar_size", i32 4}
+  !8 = !{!"clang version 9.0.0"}
+  !9 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 10, type: !10, scopeLine: 10, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13)
+  !10 = !DISubroutineType(types: !11)
+  !11 = !{!12, !12, !12, !12, !12}
+  !12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !13 = !{!14, !15, !16, !17, !18, !19, !20}
+  !14 = !DILocalVariable(name: "arg1", arg: 1, scope: !9, file: !1, line: 10, type: !12)
+  !15 = !DILocalVariable(name: "arg2", arg: 2, scope: !9, file: !1, line: 10, type: !12, flags: DIFlagArgumentNotModified)
+  !16 = !DILocalVariable(name: "arg3", arg: 3, scope: !9, file: !1, line: 10, type: !12)
+  !17 = !DILocalVariable(name: "arg4", arg: 4, scope: !9, file: !1, line: 10, type: !12, flags: DIFlagArgumentNotModified)
+  !18 = !DILocalVariable(name: "local1", scope: !9, file: !1, line: 11, type: !12)
+  !19 = !DILocalVariable(name: "local2", scope: !9, file: !1, line: 11, type: !12)
+  !20 = !DILocalVariable(name: "local3", scope: !9, file: !1, line: 11, type: !12)
+  !21 = !DILocation(line: 10, column: 13, scope: !9)
+
+...
+---
+name:            baa
+liveins:         
+  - { reg: '$edi', virtual-reg: '' }
+  - { reg: '$esi', virtual-reg: '' }
+  - { reg: '$edx', virtual-reg: '' }
+  - { reg: '$ecx', virtual-reg: '' }
+callSites:       
+  - { bb: 0, offset: 23, fwdArgRegs: 
+      - { arg: 0, reg: '$edi' }
+      - { arg: 1, reg: '$esi' }
+      - { arg: 2, reg: '$rdx' }
+      - { arg: 3, reg: '$ecx' } }
+  - { bb: 0, offset: 49, fwdArgRegs: 
+      - { arg: 0, reg: '$edi' }
+      - { arg: 1, reg: '$esi' }
+      - { arg: 2, reg: '$rdx' }
+      - { arg: 3, reg: '$ecx' } }
+body:             |
+  bb.0.entry:
+    liveins: $ecx, $edi, $edx, $esi, $r15, $r14, $rbx
+  
+    DBG_VALUE $edi, $noreg, !14, !DIExpression(), debug-location !21
+    DBG_VALUE $esi, $noreg, !15, !DIExpression(), debug-location !21
+    DBG_VALUE $edx, $noreg, !16, !DIExpression(), debug-location !21
+    DBG_VALUE $ecx, $noreg, !17, !DIExpression(), debug-location !21
+    frame-setup PUSH64r killed $r15, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 16
+    frame-setup PUSH64r killed $r14, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 24
+    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 32
+    $rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
+    CFI_INSTRUCTION def_cfa_offset 48
+    CFI_INSTRUCTION offset $rbx, -32
+    CFI_INSTRUCTION offset $r14, -24
+    CFI_INSTRUCTION offset $r15, -16
+    $r14d = MOV32rr $ecx, implicit-def $r14
+    DBG_VALUE $edx, $noreg, !16, !DIExpression(), debug-location !21
+    $r15d = MOV32rr $esi, implicit-def $r15
+    $ebx = MOV32rr $edi, implicit-def $rbx
+    $edi = MOV32rr $esi
+    MOV32mr $rsp, 1, $noreg, 8, $noreg, killed renamable $edx :: (store 4 into %ir.arg3.addr)
+    renamable $rdx = LEA64r $rsp, 1, $noreg, 8, $noreg
+    renamable $ecx = MOV32rr $r14d,
+    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, implicit-def $rax, debug-location !21
+    DBG_VALUE $noreg, $noreg, !18, !DIExpression(), debug-location !21
+    $rdx = MOV64rr renamable $rax
+    $ecx = KILL renamable $ecx, implicit-def $rcx 
+    renamable $eax = LEA64_32r renamable $rcx, 1, renamable $rbx, 0, $noreg, debug-location !21
+    renamable $edi = LEA64_32r renamable $r14, 1, renamable $r15, 0, $noreg, debug-location !21
+    CMP32rr renamable $ebx, renamable $r15d, implicit-def $eflags, implicit killed $r15, debug-location !21
+    renamable $edi = CMOV32rr killed renamable $edi, killed renamable $eax, 15, implicit killed $eflags, debug-location !21
+    DBG_VALUE $edi, $noreg, !18, !DIExpression(), debug-location !21
+    $eax = MOV32rr $ecx, debug-location !21
+    CDQ implicit-def $eax, implicit-def $edx, implicit $eax, debug-location !21
+    IDIV32r renamable $ebx, implicit-def dead $eax, implicit-def $edx, implicit-def dead $eflags, implicit $eax, implicit $edx, debug-location !21
+    $eax = MOV32rr $ecx, debug-location !21
+    renamable $eax = nsw IMUL32rr killed renamable $eax, renamable $ebx, implicit-def dead $eflags, debug-location !21
+    renamable $ecx = nsw ADD32rr renamable $ecx, renamable $r14d, implicit-def dead $eflags, implicit killed $rcx, implicit-def $rcx, debug-location !21
+    TEST32rr killed renamable $edx, renamable $edx, implicit-def $eflags, debug-location !21
+    renamable $ecx = CMOV32rr renamable $ecx, killed renamable $eax, 4, implicit killed $eflags, implicit killed $rcx, implicit-def $rcx, debug-location !21
+    DBG_VALUE $ecx, $noreg, !19, !DIExpression(), debug-location !21
+    MOV32mr $rsp, 1, $noreg, 12, $noreg, renamable $ecx, debug-location !21 :: (store 4 into %ir.local2)
+    CMP32rr renamable $ecx, renamable $r14d, implicit-def $eflags, implicit killed $r14, debug-location !21
+    renamable $ebx = CMOV32rr renamable $ebx, renamable $edi, 12, implicit killed $eflags, implicit killed $rbx, implicit-def $rbx, debug-location !21
+    renamable $ecx = nsw IMUL32rr renamable $ecx, renamable $ebx, implicit-def dead $eflags, implicit killed $rbx, implicit killed $rcx, implicit-def $rcx, debug-location !21
+    DBG_VALUE $rsp, $noreg, !19, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref), debug-location !21
+    DBG_VALUE $ecx, $noreg, !20, !DIExpression(), debug-location !21
+    $esi = MOV32ri 4, debug-location !21
+    renamable $ecx = MOV32rm $rsp, 1, $noreg, 8, $noreg, implicit-def $rcx, debug-location !21 :: (dereferenceable load 4 from %ir.arg3.addr)
+    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, implicit-def $rax, debug-location !21
+    DBG_VALUE $eax, $noreg, !14, !DIExpression(), debug-location !21
+    renamable $eax = nsw ADD32ri8 killed renamable $eax, 4, implicit-def dead $eflags, debug-location !21
+    $rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !21
+    CFI_INSTRUCTION def_cfa_offset 32, debug-location !21
+    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
+    CFI_INSTRUCTION def_cfa_offset 24, debug-location !21
+    $r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
+    DBG_VALUE $ecx, $noreg, !17, !DIExpression(DW_OP_entry_value, 1), debug-location !21
+    CFI_INSTRUCTION def_cfa_offset 16, debug-location !21
+    $r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !21
+    DBG_VALUE $esi, $noreg, !15, !DIExpression(DW_OP_entry_value, 1), debug-location !21
+    CFI_INSTRUCTION def_cfa_offset 8, debug-location !21
+    RETQ $eax, debug-location !21
+
+...

Added: llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir?rev=365467&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/dbgcall-site-lea-interpretation.mir Tue Jul  9 04:33:56 2019
@@ -0,0 +1,140 @@
+# RUN: llc -debug-entry-values -start-after=machineverifier -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT:   DW_AT_abstract_origin {{.*}} "foo")
+# CHECK-NEXT:   DW_AT_low_pc {{.*}} 
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg9 R9)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg15 R15+10)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg8 R8)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg15 R15+0, DW_OP_lit2, DW_OP_mul, DW_OP_lit8, DW_OP_plus)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg1 RDX)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_lit5, DW_OP_mul, DW_OP_lit8, DW_OP_plus)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg4 RSI)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg5 RDI)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_breg15 R15+0, DW_OP_lit2, DW_OP_mul, DW_OP_plus, DW_OP_lit4, DW_OP_plus)
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg2 RCX)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_breg15 R15+0, DW_OP_plus)
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT:   DW_AT_abstract_origin {{.*}} "foo2")
+# CHECK-NEXT:   DW_AT_low_pc {{.*}}
+# CHECK-EMPTY: 
+# CHECK-NEXT:   DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:     DW_AT_location      (DW_OP_reg5 RDI)
+# CHECK-NEXT:     DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+0, DW_OP_lit2, DW_OP_mul)
+--- |
+  ; ModuleID = 'dbgcall-site-lea-interpretation.ll'
+  source_filename = "dbgcall-site-lea-interpretation.c"
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+  
+  define dso_local i32 @baa(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr !dbg !10 {
+  entry:
+    %arg1.addr = alloca i32, align 4
+    %arg3.addr = alloca i32, align 4
+    %local1 = alloca i32, align 4
+    store i32 %arg1, i32* %arg1.addr, align 4
+    store i32 %arg3, i32* %arg3.addr, align 4
+    %0 = bitcast i32* %local1 to i8*, !dbg !14
+    %mul = mul nsw i32 %arg3, %arg1, !dbg !14
+    store i32 %mul, i32* %local1, align 4, !dbg !14
+    %add = add nsw i32 %arg2, %arg1, !dbg !14
+    %sub = sub nsw i32 %add, %arg3, !dbg !14
+    %call = call i32 @foo(i32 %mul, i32 %sub, i32* nonnull %local1, i32* nonnull %arg1.addr, i32* nonnull %arg3.addr, i32 %add), !dbg !14
+    %1 = load i32, i32* %local1, align 4, !dbg !14
+    %add2 = add nsw i32 %1, %call, !dbg !14
+    store i32 %add2, i32* %local1, align 4, !dbg !14
+    %call3 = call i32 @foo2(i32* nonnull %local1), !dbg !14
+    %2 = load i32, i32* %local1, align 4, !dbg !14
+    ret i32 %2, !dbg !14
+  }
+  
+  declare !dbg !4 dso_local i32 @foo(i32, i32, i32*, i32*, i32*, i32) local_unnamed_addr
+  
+  declare !dbg !5 dso_local i32 @foo2(i32*) local_unnamed_addr
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!6, !7, !8}
+  !llvm.ident = !{!9}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "dbgcall-site-lea-interpretation.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4, !5}
+  !4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 8, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubprogram(name: "foo2", scope: !1, file: !1, line: 9, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !6 = !{i32 2, !"Dwarf Version", i32 4}
+  !7 = !{i32 2, !"Debug Info Version", i32 3}
+  !8 = !{i32 1, !"wchar_size", i32 4}
+  !9 = !{!"clang version 9.0.0"}
+  !10 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 11, type: !11, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+  !11 = !DISubroutineType(types: !12)
+  !12 = !{!13, !13, !13, !13}
+  !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !14 = !DILocation(line: 11, column: 13, scope: !10)
+
+...
+---
+name:            baa
+liveins:         
+  - { reg: '$edi', virtual-reg: '' }
+  - { reg: '$esi', virtual-reg: '' }
+  - { reg: '$edx', virtual-reg: '' }
+callSites:       
+  - { bb: 0, offset: 21, fwdArgRegs: 
+      - { arg: 0, reg: '$edi' }
+      - { arg: 1, reg: '$esi' }
+      - { arg: 2, reg: '$rdx' }
+      - { arg: 3, reg: '$rcx' }
+      - { arg: 4, reg: '$r8' }
+      - { arg: 5, reg: '$r9d' } }
+  - { bb: 0, offset: 24, fwdArgRegs: 
+      - { arg: 0, reg: '$rdi' } }
+body:             |
+  bb.0.entry:
+    liveins: $edi, $edx, $esi, $rbx
+  
+    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 16
+    $rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
+    CFI_INSTRUCTION def_cfa_offset 32
+    CFI_INSTRUCTION offset $rbx, -16
+    $r9d = MOV32rr $esi
+    $r14 = MOV64rr $rsi
+    $r15 = MOV64rr $rdi
+    MOV32mr $rsp, 1, $noreg, 12, $noreg, renamable $edi :: (store 4 into %ir.arg1.addr)
+    MOV32mr $rsp, 1, $noreg, 8, $noreg, renamable $edx :: (store 4 into %ir.arg3.addr)
+    renamable $r9d = nsw ADD32rr killed renamable $r9d, renamable $edi, implicit-def dead $eflags, debug-location !14
+    $esi = MOV32rr $r9d, debug-location !14
+    renamable $esi = nsw SUB32rr killed renamable $esi, renamable $edx, implicit-def dead $eflags, debug-location !14
+    renamable $edx = nsw IMUL32rr killed renamable $edx, killed renamable $edi, implicit-def dead $eflags, debug-location !14
+    MOV32mr $rsp, 1, $noreg, 4, $noreg, renamable $edx, debug-location !14 :: (store 4 into %ir.local1)
+    renamable $rcx = LEA64r $r14, 1, $r15, 0, $noreg
+    renamable $rdi = LEA64r $r14, 2, $r15, 4, $noreg
+    renamable $rsi = LEA64r $r14, 1, $noreg, 0, $noreg
+    renamable $rdx = LEA64r $r14, 4, $r14, 8, $noreg
+    renamable $r8 = LEA64r $noreg, 2, $r15, 8, $noreg
+    renamable $r9 = LEA64r  $noreg, 1, $r15, 10, $noreg, implicit-def $r9d
+    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $edi, implicit $esi, implicit $rdx, implicit $rcx, implicit $r8, implicit $r9d, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !14
+    ADD32mr $rsp, 1, $noreg, 4, $noreg, killed renamable $eax, implicit-def dead $eflags, debug-location !14 :: (store 4 into %ir.local1), (dereferenceable load 4 from %ir.local1)
+    $rdi = LEA64r $r14, 1, killed $r14, 0, $noreg
+    CALL64pcrel32 @foo2, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def dead $eax, debug-location !14
+    renamable $eax = MOV32rm $rsp, 1, $noreg, 4, $noreg, debug-location !14 :: (dereferenceable load 4 from %ir.local1)
+    $rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !14
+    CFI_INSTRUCTION def_cfa_offset 16, debug-location !14
+    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !14
+    CFI_INSTRUCTION def_cfa_offset 8, debug-location !14
+    RETQ $eax, debug-location !14
+
+...

Added: llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir?rev=365467&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir (added)
+++ llvm/trunk/test/DebugInfo/MIR/X86/debug-call-site-param.mir Tue Jul  9 04:33:56 2019
@@ -0,0 +1,158 @@
+# RUN: llc -debug-entry-values -filetype=obj -mtriple=x86_64-unknown-unknown -start-after=machineverifier -o - %s| llvm-dwarfdump - | FileCheck %s
+#
+# extern void foo(int *a, int b, int c, int d, int e, int f);
+# extern int getVal();
+#
+# void baa(int arg1, int arg2, int arg3) {
+#   int local1 = getVal();
+#   foo(&local1, arg2, 10, 15, arg3 + 3, arg1 + arg2);
+# }
+#
+# CHECK: DW_TAG_GNU_call_site
+# CHECK: DW_AT_abstract_origin {{.*}} "getVal"
+#
+# CHECK: DW_TAG_GNU_call_site
+# CHECK: DW_AT_abstract_origin {{.*}} "foo"
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:  DW_AT_location      (DW_OP_reg2 RCX)
+# CHECK-NEXT:  DW_AT_GNU_call_site_value   (DW_OP_lit15)
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg1 RDX)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_lit10)
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg4 RSI)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_breg3 RBX+0)
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg5 RDI)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_fbreg +12)
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg9 R9)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_breg15 R15+0, DW_OP_breg3 RBX+0, DW_OP_plus)
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT: DW_AT_location      (DW_OP_reg8 R8)
+# CHECK-NEXT: DW_AT_GNU_call_site_value   (DW_OP_breg14 R14+3)
+
+--- |
+  ; ModuleID = 'test.c'
+  source_filename = "test.c"
+  target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+  
+  ; Function Attrs: nounwind uwtable
+  define dso_local void @baa(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr !dbg !10 {
+  entry:
+    %local1 = alloca i32, align 4
+    call void @llvm.dbg.value(metadata i32 %arg1, metadata !15, metadata !DIExpression()), !dbg !19
+    call void @llvm.dbg.value(metadata i32 %arg2, metadata !16, metadata !DIExpression()), !dbg !20
+    call void @llvm.dbg.value(metadata i32 %arg3, metadata !17, metadata !DIExpression()), !dbg !21
+    %0 = bitcast i32* %local1 to i8*, !dbg !22
+    %call = tail call i32 (...) @getVal(), !dbg !23
+    call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !24
+    store i32 %call, i32* %local1, align 4, !dbg !24
+    %add = add nsw i32 %arg3, 3, !dbg !24
+    %add1 = add nsw i32 %arg2, %arg1, !dbg !24
+    call void @llvm.dbg.value(metadata i32* %local1, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !24
+    call void @foo(i32* nonnull %local1, i32 %arg2, i32 10, i32 15, i32 %add, i32 %add1), !dbg !24
+    ret void, !dbg !24
+  }
+  
+  declare !dbg !4 dso_local i32 @getVal(...) local_unnamed_addr
+  
+  declare !dbg !5 dso_local void @foo(i32*, i32, i32, i32, i32, i32) local_unnamed_addr
+  
+  ; Function Attrs: nounwind readnone speculatable
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!6, !7, !8}
+  !llvm.ident = !{!9}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "test.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4, !5}
+  !4 = !DISubprogram(name: "getVal", scope: !1, file: !1, line: 2, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !6 = !{i32 2, !"Dwarf Version", i32 4}
+  !7 = !{i32 2, !"Debug Info Version", i32 3}
+  !8 = !{i32 1, !"wchar_size", i32 4}
+  !9 = !{!"clang version 9.0.0"}
+  !10 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+  !11 = !DISubroutineType(types: !12)
+  !12 = !{null, !13, !13, !13}
+  !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !14 = !{!15, !16, !17, !18}
+  !15 = !DILocalVariable(name: "arg1", arg: 1, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
+  !16 = !DILocalVariable(name: "arg2", arg: 2, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
+  !17 = !DILocalVariable(name: "arg3", arg: 3, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
+  !18 = !DILocalVariable(name: "local1", scope: !10, file: !1, line: 5, type: !13)
+  !19 = !DILocation(line: 4, column: 14, scope: !10)
+  !20 = !DILocation(line: 4, column: 24, scope: !10)
+  !21 = !DILocation(line: 4, column: 34, scope: !10)
+  !22 = !DILocation(line: 5, column: 3, scope: !10)
+  !23 = !DILocation(line: 5, column: 16, scope: !10)
+  !24 = !DILocation(line: 5, column: 7, scope: !10)
+
+...
+---
+name:            baa
+liveins:         
+  - { reg: '$edi', virtual-reg: '' }
+  - { reg: '$esi', virtual-reg: '' }
+  - { reg: '$edx', virtual-reg: '' }
+callSites:       
+  - { bb: 0, offset: 21, fwdArgRegs: [] }
+  - { bb: 0, offset: 31, fwdArgRegs: 
+      - { arg: 0, reg: '$rdi' }
+      - { arg: 1, reg: '$esi' }
+      - { arg: 2, reg: '$edx' }
+      - { arg: 3, reg: '$ecx' }
+      - { arg: 4, reg: '$r8d' }
+      - { arg: 5, reg: '$r9d' } }
+body:             |
+  bb.0.entry:
+    liveins: $edi, $edx, $esi, $r15, $r14, $rbx
+  
+    DBG_VALUE $edi, $noreg, !15, !DIExpression(), debug-location !19
+    DBG_VALUE $esi, $noreg, !16, !DIExpression(), debug-location !20
+    DBG_VALUE $edx, $noreg, !17, !DIExpression(), debug-location !21
+    frame-setup PUSH64r killed $r15, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 16
+    frame-setup PUSH64r killed $r14, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 24
+    frame-setup PUSH64r killed $rbx, implicit-def $rsp, implicit $rsp
+    CFI_INSTRUCTION def_cfa_offset 32
+    $rsp = frame-setup SUB64ri8 $rsp, 16, implicit-def dead $eflags
+    CFI_INSTRUCTION def_cfa_offset 48
+    CFI_INSTRUCTION offset $rbx, -32
+    CFI_INSTRUCTION offset $r14, -24
+    CFI_INSTRUCTION offset $r15, -16
+    $r14d = MOV32rr $edx, implicit-def $r14
+    $ebx = MOV32rr $esi, implicit-def $rbx
+    $r15d = MOV32rr $edi, implicit-def $r15
+    DBG_VALUE $r14d, $noreg, !17, !DIExpression(), debug-location !21
+    DBG_VALUE $ebx, $noreg, !16, !DIExpression(), debug-location !20
+    DBG_VALUE $r15d, $noreg, !15, !DIExpression(), debug-location !19
+    dead $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, implicit-def $al, debug-location !23
+    CALL64pcrel32 @getVal, csr_64, implicit $rsp, implicit $ssp, implicit $al, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !23
+    DBG_VALUE $eax, $noreg, !18, !DIExpression(), debug-location !24
+    MOV32mr $rsp, 1, $noreg, 12, $noreg, killed renamable $eax, debug-location !24 :: (store 4 into %ir.local1)
+    renamable $r8d = LEA64_32r killed renamable $r14, 1, $noreg, 3, $noreg, debug-location !24
+    renamable $r9d = LEA64_32r killed renamable $r15, 1, renamable $rbx, 0, $noreg, debug-location !24
+    DBG_VALUE $rsp, $noreg, !18, !DIExpression(DW_OP_plus_uconst, 12, DW_OP_deref), debug-location !24
+    renamable $rdi = LEA64r $rsp, 1, $noreg, 12, $noreg
+    $esi = MOV32rr $ebx, implicit killed $rbx, debug-location !24
+    $edx = MOV32ri 10, debug-location !24
+    $ecx = MOV32ri 15, debug-location !24
+    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $esi, implicit $edx, implicit killed $ecx, implicit $r8d, implicit $r9d, implicit-def $rsp, implicit-def $ssp, debug-location !24
+    $rsp = frame-destroy ADD64ri8 $rsp, 16, implicit-def dead $eflags, debug-location !24
+    CFI_INSTRUCTION def_cfa_offset 32, debug-location !24
+    $rbx = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !24
+    CFI_INSTRUCTION def_cfa_offset 24, debug-location !24
+    $r14 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !24
+    CFI_INSTRUCTION def_cfa_offset 16, debug-location !24
+    $r15 = frame-destroy POP64r implicit-def $rsp, implicit $rsp, debug-location !24
+    CFI_INSTRUCTION def_cfa_offset 8, debug-location !24
+    RETQ debug-location !24
+
+...

Modified: 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=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll (original)
+++ llvm/trunk/test/DebugInfo/X86/dwarf-callsite-related-attrs.ll Tue Jul  9 04:33:56 2019
@@ -14,14 +14,14 @@
 
 ; REQUIRES: object-emission
 ; RUN: %llc_dwarf -mtriple=x86_64-- < %s -o - | FileCheck %s -check-prefix=ASM
-; RUN: %llc_dwarf -mtriple=x86_64-- < %s -filetype=obj -o %t.o
+; RUN: %llc_dwarf -debugger-tune=lldb -mtriple=x86_64-- < %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
+; STATS: "call site DIEs":6
 
 @sink = global i32 0, align 4, !dbg !0
 
@@ -85,6 +85,9 @@ entry:
 ; OBJ:   DW_TAG_call_site
 ; OBJ:     DW_AT_call_origin ([[foo_sp]])
 ; OBJ:     DW_AT_call_return_pc
+; OBJ:   DW_TAG_call_site
+; OBJ:     DW_AT_call_target
+; OBJ:     DW_AT_call_return_pc
 define i32 @main() !dbg !29 {
 entry:
   call void @_Z3foov(), !dbg !32

Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll?rev=365467&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll (added)
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/stats-dbg-callsite-info.ll Tue Jul  9 04:33:56 2019
@@ -0,0 +1,76 @@
+; RUN: llc -debug-entry-values %s -o - -filetype=obj \
+; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
+;
+; The LLVM IR file was generated on this source code by using
+; option '-femit-param-entry-values'.
+;
+; extern void foo(int *a, int b, int c, int d, int e, int f);
+; extern int getVal();
+;
+; void baa(int arg1, int arg2, int arg3) {
+;   int local1 = getVal();
+;   foo(&local1, arg2, 10, 15, arg3 + 3, arg1 + arg2);
+; }
+;
+; CHECK: "call site DIEs":2
+; CHECK-SAME: "call site parameter DIEs":6
+;
+; ModuleID = 'test.c'
+source_filename = "test.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define dso_local void @baa(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr #0 !dbg !10 {
+entry:
+  %local1 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata i32 %arg1, metadata !15, metadata !DIExpression()), !dbg !19
+  call void @llvm.dbg.value(metadata i32 %arg2, metadata !16, metadata !DIExpression()), !dbg !20
+  call void @llvm.dbg.value(metadata i32 %arg3, metadata !17, metadata !DIExpression()), !dbg !21
+  %0 = bitcast i32* %local1 to i8*, !dbg !22
+  %call = tail call i32 (...) @getVal(), !dbg !23
+  call void @llvm.dbg.value(metadata i32 %call, metadata !18, metadata !DIExpression()), !dbg !24
+  store i32 %call, i32* %local1, align 4, !dbg !24
+  %add = add nsw i32 %arg3, 3, !dbg !24
+  %add1 = add nsw i32 %arg2, %arg1, !dbg !24
+  call void @llvm.dbg.value(metadata i32* %local1, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !24
+  call void @foo(i32* nonnull %local1, i32 %arg2, i32 10, i32 15, i32 %add, i32 %add1), !dbg !24
+  ret void, !dbg !24
+}
+
+declare !dbg !4 dso_local i32 @getVal(...) local_unnamed_addr
+
+declare !dbg !5 dso_local void @foo(i32*, i32, i32, i32, i32, i32) local_unnamed_addr
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/dir")
+!2 = !{}
+!3 = !{!4, !5}
+!4 = !DISubprogram(name: "getVal", scope: !1, file: !1, line: 2, spFlags: DISPFlagOptimized, retainedNodes: !2)
+!5 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+!6 = !{i32 2, !"Dwarf Version", i32 4}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+!8 = !{i32 1, !"wchar_size", i32 4}
+!9 = !{!"clang version 9.0.0"}
+!10 = distinct !DISubprogram(name: "baa", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{null, !13, !13, !13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{!15, !16, !17, !18}
+!15 = !DILocalVariable(name: "arg1", arg: 1, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
+!16 = !DILocalVariable(name: "arg2", arg: 2, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
+!17 = !DILocalVariable(name: "arg3", arg: 3, scope: !10, file: !1, line: 4, type: !13, flags: DIFlagArgumentNotModified)
+!18 = !DILocalVariable(name: "local1", scope: !10, file: !1, line: 5, type: !13)
+!19 = !DILocation(line: 4, column: 14, scope: !10)
+!20 = !DILocation(line: 4, column: 24, scope: !10)
+!21 = !DILocation(line: 4, column: 34, scope: !10)
+!22 = !DILocation(line: 5, column: 3, scope: !10)
+!23 = !DILocation(line: 5, column: 16, scope: !10)
+!24 = !DILocation(line: 5, column: 7, scope: !10)

Modified: llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp?rev=365467&r1=365466&r2=365467&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp (original)
+++ llvm/trunk/tools/llvm-dwarfdump/Statistics.cpp Tue Jul  9 04:33:56 2019
@@ -56,9 +56,12 @@ 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) or
-  /// (DW_AT_call_file & DW_AT_call_line).
+  /// Total number of call site entries (DW_AT_call_file & DW_AT_call_line).
   unsigned CallSiteEntries = 0;
+  /// Total number of call site DIEs (DW_TAG_call_site).
+  unsigned CallSiteDIEs = 0;
+  /// Total number of call site parameter DIEs (DW_TAG_call_site_parameter).
+  unsigned CallSiteParamDIEs = 0;
   /// Total byte size of concrete functions. This byte size includes
   /// inline functions contained in the concrete functions.
   uint64_t FunctionSize = 0;
@@ -94,8 +97,15 @@ static void collectStatsForDie(DWARFDie
   uint64_t BytesCovered = 0;
   uint64_t OffsetToFirstDefinition = 0;
 
-  if (Die.getTag() == dwarf::DW_TAG_call_site) {
-    GlobalStats.CallSiteEntries++;
+  if (Die.getTag() == dwarf::DW_TAG_call_site ||
+      Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
+    GlobalStats.CallSiteDIEs++;
+    return;
+  }
+
+  if (Die.getTag() == dwarf::DW_TAG_call_site_parameter ||
+      Die.getTag() == dwarf::DW_TAG_GNU_call_site_parameter) {
+    GlobalStats.CallSiteParamDIEs++;
     return;
   }
 
@@ -387,6 +397,8 @@ bool collectStatsForObjectFile(ObjectFil
   printDatum(OS, "source variables", VarParamTotal);
   printDatum(OS, "variables with location", VarParamWithLoc);
   printDatum(OS, "call site entries", GlobalStats.CallSiteEntries);
+  printDatum(OS, "call site DIEs", GlobalStats.CallSiteDIEs);
+  printDatum(OS, "call site parameter DIEs", GlobalStats.CallSiteParamDIEs);
   printDatum(OS, "scope bytes total",
              GlobalStats.ScopeBytesFromFirstDefinition);
   printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);




More information about the llvm-commits mailing list