summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp31
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h10
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp68
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h4
4 files changed, 110 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index d8d6f76d71e..443c8879f13 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -730,7 +730,8 @@ DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
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::constructSubprogramScopeDIE(const DISubprogram *Sub, Lexi
!includeMinimalInlineScopes())
ScopeDIE.addChild(
DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters));
+
+ return ScopeDIE;
}
DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
@@ -807,6 +810,32 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
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());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 9bf1ce18b3a..6389ccd686d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -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);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index ede606131ff..ab3559d63cc 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -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::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,
}
}
+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 MachineInstr *MI) {
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 MachineFunction *MF) {
}
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
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index ba40ad28eb7..e115eb771fb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -424,6 +424,10 @@ class DwarfDebug : public DebugHandlerBase {
/// 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);
OpenPOWER on IntegriCloud