15 changes: 0 additions & 15 deletions llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,6 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {
return LabelsAfterInsn.lookup(MI);
}

// Return the function-local offset of an instruction.
const MCExpr *
DebugHandlerBase::getFunctionLocalOffsetAfterInsn(const MachineInstr *MI) {
MCContext &MC = Asm->OutContext;

MCSymbol *Start = Asm->getFunctionBegin();
const auto *StartRef = MCSymbolRefExpr::create(Start, MC);

MCSymbol *AfterInsn = getLabelAfterInsn(MI);
assert(AfterInsn && "Expected label after instruction");
const auto *AfterRef = MCSymbolRefExpr::create(AfterInsn, MC);

return MCBinaryExpr::createSub(AfterRef, StartRef, MC);
}

/// If this type is derived from a base type then return base type size.
uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
assert(Ty);
Expand Down
18 changes: 7 additions & 11 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -956,9 +956,11 @@ DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const {
}
}

DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail,
const MCSymbol *PCAddr, const MCExpr *PCOffset, unsigned CallReg) {
DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
const DISubprogram *CalleeSP,
bool IsTail,
const MCSymbol *PCAddr,
unsigned CallReg) {
// Insert a call site entry DIE within ScopeDIE.
DIE &CallSiteDIE = createAndAddDIE(getDwarf5OrGNUTag(dwarf::DW_TAG_call_site),
ScopeDIE, nullptr);
Expand All @@ -984,8 +986,8 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
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);
assert(PCAddr && "Missing return PC information for a call");
addLabelAddress(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCAddr);
}

return CallSiteDIE;
Expand Down Expand Up @@ -1285,12 +1287,6 @@ void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form,
Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, Form, DIEExpr(Expr));
}

void DwarfCompileUnit::addAddressExpr(DIE &Die, dwarf::Attribute Attribute,
const MCExpr *Expr) {
Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr,
DIEExpr(Expr));
}

void DwarfCompileUnit::applySubprogramAttributesToDefinition(
const DISubprogram *SP, DIE &SPDie) {
auto *SPDecl = SP->getDeclaration();
Expand Down
12 changes: 2 additions & 10 deletions llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,17 +242,12 @@ class DwarfCompileUnit final : public DwarfUnit {
/// 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 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, since for
/// GDB + DWARF 5 tuning we still generate PC info for tail calls) or be the
/// function-local offset to PC value after the call instruction.
/// \p PCAddr points to the PC value after the call instruction.
/// \p CallReg is a register location for an indirect call. For direct calls
/// the \p CallReg is set to 0.
DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP,
bool IsTail, const MCSymbol *PCAddr,
const MCExpr *PCOffset, unsigned CallReg);
unsigned CallReg);
/// Construct call site parameter DIEs for the \p CallSiteDIE. The \p Params
/// were collected by the \ref collectCallSiteParameters.
/// Note: The order of parameters does not matter, since debuggers recognize
Expand Down Expand Up @@ -340,9 +335,6 @@ class DwarfCompileUnit final : public DwarfUnit {
/// Add a Dwarf expression attribute data and value.
void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr);

/// Add an attribute containing an address expression to \p Die.
void addAddressExpr(DIE &Die, dwarf::Attribute Attribute, const MCExpr *Expr);

void applySubprogramAttributesToDefinition(const DISubprogram *SP,
DIE &SPDie);

Expand Down
23 changes: 6 additions & 17 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,6 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,

const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
assert(TII && "TargetInstrInfo not found: cannot label tail calls");
bool ApplyGNUExtensions = getDwarfVersion() == 4 && tuneForGDB();

// Emit call site entries for each call or tail call in the function.
for (const MachineBasicBlock &MBB : MF) {
Expand Down Expand Up @@ -781,25 +780,16 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
const MachineInstr *TopLevelCallMI =
MI.isInsideBundle() ? &*getBundleStart(MI.getIterator()) : &MI;

// For tail calls, for non-gdb tuning, no return PC information is needed.
// For tail calls, 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 =
const MCSymbol *PCAddr =
(IsTail && !tuneForGDB())
? nullptr
: getFunctionLocalOffsetAfterInsn(TopLevelCallMI);

// Return 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(TopLevelCallMI))
: nullptr;
: const_cast<MCSymbol *>(getLabelAfterInsn(TopLevelCallMI));

assert((IsTail || PCOffset || PCAddr) &&
"Call without return PC information");
assert((IsTail || PCAddr) && "Call without return PC information");

LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
<< (CalleeDecl ? CalleeDecl->getName()
Expand All @@ -808,9 +798,8 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
->getName(CallReg)))
<< (IsTail ? " [IsTail]" : "") << "\n");

DIE &CallSiteDIE =
CU.constructCallSiteEntryDIE(ScopeDIE, CalleeSP, IsTail, PCAddr,
PCOffset, CallReg);
DIE &CallSiteDIE = CU.constructCallSiteEntryDIE(ScopeDIE, CalleeSP,
IsTail, PCAddr, CallReg);

// GDB and LLDB support call site parameter debug info.
if (Asm->TM.Options.EnableDebugEntryValues &&
Expand Down
53 changes: 39 additions & 14 deletions llvm/lib/IR/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,41 @@ bool DebugInfoFinder::addScope(DIScope *Scope) {
return true;
}

static MDNode *updateLoopMetadataDebugLocationsImpl(
MDNode *OrigLoopID,
function_ref<DILocation *(const DILocation &)> Updater) {
assert(OrigLoopID && OrigLoopID->getNumOperands() > 0 &&
"Loop ID needs at least one operand");
assert(OrigLoopID && OrigLoopID->getOperand(0).get() == OrigLoopID &&
"Loop ID should refer to itself");

// Save space for the self-referential LoopID.
SmallVector<Metadata *, 4> MDs = {nullptr};

for (unsigned i = 1; i < OrigLoopID->getNumOperands(); ++i) {
Metadata *MD = OrigLoopID->getOperand(i);
if (DILocation *DL = dyn_cast<DILocation>(MD)) {
if (DILocation *NewDL = Updater(*DL))
MDs.push_back(NewDL);
} else
MDs.push_back(MD);
}

MDNode *NewLoopID = MDNode::getDistinct(OrigLoopID->getContext(), MDs);
// Insert the self-referential LoopID.
NewLoopID->replaceOperandWith(0, NewLoopID);
return NewLoopID;
}

void llvm::updateLoopMetadataDebugLocations(
Instruction &I, function_ref<DILocation *(const DILocation &)> Updater) {
MDNode *OrigLoopID = I.getMetadata(LLVMContext::MD_loop);
if (!OrigLoopID)
return;
MDNode *NewLoopID = updateLoopMetadataDebugLocationsImpl(OrigLoopID, Updater);
I.setMetadata(LLVMContext::MD_loop, NewLoopID);
}

static MDNode *stripDebugLocFromLoopID(MDNode *N) {
assert(!N->operands().empty() && "Missing self reference?");

Expand All @@ -294,20 +329,10 @@ static MDNode *stripDebugLocFromLoopID(MDNode *N) {
}))
return nullptr;

SmallVector<Metadata *, 4> Args;
// Reserve operand 0 for loop id self reference.
auto TempNode = MDNode::getTemporary(N->getContext(), None);
Args.push_back(TempNode.get());
// Add all non-debug location operands back.
for (auto Op = N->op_begin() + 1; Op != N->op_end(); Op++) {
if (!isa<DILocation>(*Op))
Args.push_back(*Op);
}

// Set the first operand to itself.
MDNode *LoopID = MDNode::get(N->getContext(), Args);
LoopID->replaceOperandWith(0, LoopID);
return LoopID;
auto dropDebugLoc = [](const DILocation &) -> DILocation * {
return nullptr;
};
return updateLoopMetadataDebugLocationsImpl(N, dropDebugLoc);
}

bool llvm::stripDebugInfo(Function &F) {
Expand Down
38 changes: 5 additions & 33 deletions llvm/lib/Transforms/Utils/InlineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1356,34 +1356,6 @@ static DebugLoc inlineDebugLoc(DebugLoc OrigDL, DILocation *InlinedAt,
IA);
}

/// Returns the LoopID for a loop which has has been cloned from another
/// function for inlining with the new inlined-at start and end locs.
static MDNode *inlineLoopID(const MDNode *OrigLoopId, DILocation *InlinedAt,
LLVMContext &Ctx,
DenseMap<const MDNode *, MDNode *> &IANodes) {
assert(OrigLoopId && OrigLoopId->getNumOperands() > 0 &&
"Loop ID needs at least one operand");
assert(OrigLoopId && OrigLoopId->getOperand(0).get() == OrigLoopId &&
"Loop ID should refer to itself");

// Save space for the self-referential LoopID.
SmallVector<Metadata *, 4> MDs = {nullptr};

for (unsigned i = 1; i < OrigLoopId->getNumOperands(); ++i) {
Metadata *MD = OrigLoopId->getOperand(i);
// Update the DILocations to encode the inlined-at metadata.
if (DILocation *DL = dyn_cast<DILocation>(MD))
MDs.push_back(inlineDebugLoc(DL, InlinedAt, Ctx, IANodes));
else
MDs.push_back(MD);
}

MDNode *NewLoopID = MDNode::getDistinct(Ctx, MDs);
// Insert the self-referential LoopID.
NewLoopID->replaceOperandWith(0, NewLoopID);
return NewLoopID;
}

/// Update inlined instructions' line numbers to
/// to encode location where these instructions are inlined.
static void fixupLineNumbers(Function *Fn, Function::iterator FI,
Expand Down Expand Up @@ -1415,11 +1387,11 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
BI != BE; ++BI) {
// Loop metadata needs to be updated so that the start and end locs
// reference inlined-at locations.
if (MDNode *LoopID = BI->getMetadata(LLVMContext::MD_loop)) {
MDNode *NewLoopID =
inlineLoopID(LoopID, InlinedAtNode, BI->getContext(), IANodes);
BI->setMetadata(LLVMContext::MD_loop, NewLoopID);
}
auto updateLoopInfoLoc = [&Ctx, &InlinedAtNode, &IANodes](
const DILocation &Loc) -> DILocation * {
return inlineDebugLoc(&Loc, InlinedAtNode, Ctx, IANodes).get();
};
updateLoopMetadataDebugLocations(*BI, updateLoopInfoLoc);

if (!NoInlineLineTables)
if (DebugLoc DL = BI->getDebugLoc()) {
Expand Down
11 changes: 9 additions & 2 deletions llvm/test/DebugInfo/X86/debug_addr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
; }
;
; void bar() {
; foo();
; }

; DWARF4: .debug_info contents:
Expand All @@ -18,11 +19,14 @@
; DWARF4-NOT: DW_TAG_{{.*}}
; DWARF4: DW_AT_GNU_dwo_name{{.*}}test.dwo
; DWARF4: DW_AT_GNU_addr_base{{.*}}0x00000000
; DWARF4: DW_TAG_GNU_call_site
; DWARF4: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000002) address = 0x0000000000000018 ".text")
; DWARF4: .debug_addr contents:
; DWARF4-NEXT: 0x00000000: Addr Section: length = 0x00000000, version = 0x0004, addr_size = 0x04, seg_size = 0x00
; DWARF4-NEXT: Addrs: [
; DWARF4-NEXT: 0x00000000
; DWARF4-NEXT: 0x00000010
; DWARF4-NEXT: 0x00000018
; DWARF4-NEXT: ]

; DWARF5: .debug_info contents:
Expand All @@ -33,11 +37,13 @@
; DWARF5: DW_AT_dwo_name{{.*}}test.dwo
; DWARF5: DW_AT_addr_base{{.*}}0x00000008
; DWARF5: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000000) address = 0x0000000000000000 ".text")
; DWARF5: DW_AT_call_return_pc [DW_FORM_addrx] (indexed (00000002) address = 0x0000000000000018 ".text")
; DWARF5: .debug_addr contents:
; DWARF5-NEXT: 0x00000000: Addr Section: length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00
; DWARF5-NEXT: 0x00000000: Addr Section: length = 0x00000010, version = 0x0005, addr_size = 0x04, seg_size = 0x00
; DWARF5-NEXT: Addrs: [
; DWARF5-NEXT: 0x00000000
; DWARF5-NEXT: 0x00000010
; DWARF5-NEXT: 0x00000018
; DWARF5-NEXT: ]

; ModuleID = './test.c'
Expand All @@ -54,6 +60,7 @@ entry:
; Function Attrs: noinline nounwind optnone
define void @bar() #0 !dbg !13 {
entry:
call void @foo(), !dbg !14
ret void, !dbg !14
}

Expand All @@ -76,5 +83,5 @@ attributes #0 = { noinline nounwind optnone }
!10 = !DISubroutineType(types: !11)
!11 = !{null}
!12 = !DILocation(line: 2, column: 3, scope: !8)
!13 = distinct !DISubprogram(name: "bar", scope: !9, file: !9, line: 5, type: !10, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: false, unit: !0)
!13 = distinct !DISubprogram(name: "bar", scope: !9, file: !9, line: 5, type: !10, isLocal: false, isDefinition: true, flags: DIFlagAllCallsDescribed, scopeLine: 5, isOptimized: false, unit: !0)
!14 = !DILocation(line: 6, column: 3, scope: !13)
25 changes: 25 additions & 0 deletions llvm/test/tools/dsymutil/Inputs/call-site-entry.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* This file is used to test dsymutil support for call site entries
* (DW_TAG_call_site / DW_AT_call_return_pc).
*
* Instructions for regenerating binaries (on Darwin/x86_64):
*
* 1. Copy the source to a top-level directory to work around having absolute
* paths in the symtab's OSO entries.
*
* mkdir -p /Inputs/ && cp call-site-entry.c /Inputs && cd /Inputs
*
* 2. Compile with call site info enabled.
*
* clang -g -O1 -Xclang -disable-llvm-passes call-site-entry.c -c -o call-site-entry.macho.x86_64.o
* clang call-site-entry.macho.x86_64.o -o call-site-entry.macho.x86_64
*
* 3. Copy the binaries back into the repo's Inputs directory. You'll need
* -oso-prepend-path=%p to link.
*/

__attribute__((optnone)) int f() {}

int main() {
f();
}
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions llvm/test/tools/dsymutil/call-site-entry-linking.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
RUN: dsymutil -oso-prepend-path=%p %p/Inputs/call-site-entry.macho.x86_64 -o %t.dSYM
RUN: llvm-dwarfdump %t.dSYM | FileCheck %s -implicit-check-not=DW_AT_call_return_pc

CHECK: DW_AT_call_return_pc (0x0000000100000fa4)
4 changes: 4 additions & 0 deletions llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,10 @@ unsigned DwarfLinkerForBinary::DIECloner::cloneAddressAttribute(
// it. Otherwise (when no relocations where applied) just use the
// one we just decoded.
Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset;
} else if (AttrSpec.Attr == dwarf::DW_AT_call_return_pc) {
// Relocate a return PC address within a call site entry.
if (Die.getTag() == dwarf::DW_TAG_call_site)
Addr += Info.PCOffset;
}

Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr),
Expand Down