Skip to content

Commit 651cdff

Browse files
committed
[DebugInfo][DWARF] Add DW_AT_alloc_type support (in LLVM ID space)
LLVM currently stores heapallocsite information in CodeView debuginfo, but not in DWARF debuginfo. heapallocsite information is useful for profiling and memory analysis. The DWARF v6 working draft includes this feature as DW_AT_alloc_type; but since that is not yet an official standard, use LLVM-private ID space for now.
1 parent 4f58c82 commit 651cdff

File tree

6 files changed

+61
-20
lines changed

6 files changed

+61
-20
lines changed

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,9 @@ HANDLE_DW_AT(0x3e0a, LLVM_ptrauth_authentication_mode, 0, LLVM)
625625
HANDLE_DW_AT(0x3e0b, LLVM_num_extra_inhabitants, 0, LLVM)
626626
HANDLE_DW_AT(0x3e0c, LLVM_stmt_sequence, 0, LLVM)
627627
HANDLE_DW_AT(0x3e0d, LLVM_coro_suspend_idx, 0, LLVM)
628+
// The DWARF v6 working draft defines DW_AT_alloc_type; use this LLVM-private ID
629+
// until that is released as an official standard.
630+
HANDLE_DW_AT(0x3e0e, LLVM_alloc_type, 0, LLVM)
628631

629632
// Apple extensions.
630633

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,12 +1291,10 @@ DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const {
12911291
}
12921292
}
12931293

1294-
DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
1295-
const DISubprogram *CalleeSP,
1296-
bool IsTail,
1297-
const MCSymbol *PCAddr,
1298-
const MCSymbol *CallAddr,
1299-
unsigned CallReg) {
1294+
DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
1295+
DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail,
1296+
const MCSymbol *PCAddr, const MCSymbol *CallAddr, unsigned CallReg,
1297+
DIType *AllocSiteTy) {
13001298
// Insert a call site entry DIE within ScopeDIE.
13011299
DIE &CallSiteDIE = createAndAddDIE(getDwarf5OrGNUTag(dwarf::DW_TAG_call_site),
13021300
ScopeDIE, nullptr);
@@ -1305,7 +1303,7 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
13051303
// Indirect call.
13061304
addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target),
13071305
MachineLocation(CallReg));
1308-
} else {
1306+
} else if (CalleeSP) {
13091307
DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
13101308
assert(CalleeDIE && "Could not create DIE for call site entry origin");
13111309
if (AddLinkageNamesToDeclCallOriginsForTuning(DD) &&
@@ -1350,6 +1348,10 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
13501348
getDwarf5OrGNUAttr(dwarf::DW_AT_call_return_pc), PCAddr);
13511349
}
13521350

1351+
if (AllocSiteTy) {
1352+
addType(CallSiteDIE, AllocSiteTy, dwarf::DW_AT_LLVM_alloc_type);
1353+
}
1354+
13531355
return CallSiteDIE;
13541356
}
13551357

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@ class DwarfCompileUnit final : public DwarfUnit {
289289
/// the \p CallReg is set to 0.
290290
DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP,
291291
bool IsTail, const MCSymbol *PCAddr,
292-
const MCSymbol *CallAddr, unsigned CallReg);
292+
const MCSymbol *CallAddr, unsigned CallReg,
293+
DIType *AllocSiteTy);
293294
/// Construct call site parameter DIEs for the \p CallSiteDIE. The \p Params
294295
/// were collected by the \ref collectCallSiteParameters.
295296
/// Note: The order of parameters does not matter, since debuggers recognize

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -936,28 +936,29 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
936936
if (MI.hasDelaySlot() && !delaySlotSupported(*&MI))
937937
return;
938938

939+
DIType *AllocSiteTy = dyn_cast_or_null<DIType>(MI.getHeapAllocMarker());
940+
939941
// If this is a direct call, find the callee's subprogram.
940942
// In the case of an indirect call find the register that holds
941943
// the callee.
942944
const MachineOperand &CalleeOp = TII->getCalleeOperand(MI);
943-
if (!CalleeOp.isGlobal() &&
944-
(!CalleeOp.isReg() || !CalleeOp.getReg().isPhysical()))
945-
continue;
946945

947946
unsigned CallReg = 0;
948947
const DISubprogram *CalleeSP = nullptr;
949948
const Function *CalleeDecl = nullptr;
950-
if (CalleeOp.isReg()) {
951-
CallReg = CalleeOp.getReg();
952-
if (!CallReg)
953-
continue;
954-
} else {
949+
if (CalleeOp.isReg() && CalleeOp.getReg().isPhysical()) {
950+
CallReg = CalleeOp.getReg(); // might be zero
951+
} else if (CalleeOp.isGlobal()) {
955952
CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
956-
if (!CalleeDecl || !CalleeDecl->getSubprogram())
957-
continue;
958-
CalleeSP = CalleeDecl->getSubprogram();
953+
if (CalleeDecl)
954+
CalleeSP = CalleeDecl->getSubprogram(); // might be nullptr
959955
}
960956

957+
// Omit DIE if we can't tell where the call goes *and* we don't want to
958+
// add metadata to it.
959+
if (CalleeSP == nullptr && CallReg == 0 && AllocSiteTy == nullptr)
960+
continue;
961+
961962
// TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
962963

963964
bool IsTail = TII->isTailCall(MI);
@@ -991,7 +992,7 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
991992
<< (IsTail ? " [IsTail]" : "") << "\n");
992993

993994
DIE &CallSiteDIE = CU.constructCallSiteEntryDIE(
994-
ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg);
995+
ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg, AllocSiteTy);
995996

996997
// Optionally emit call-site-param debug info.
997998
if (emitDebugEntryValues()) {

llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ static bool isODRAttribute(uint16_t Attr) {
109109
case dwarf::DW_AT_specification:
110110
case dwarf::DW_AT_abstract_origin:
111111
case dwarf::DW_AT_import:
112+
case dwarf::DW_AT_LLVM_alloc_type:
112113
return true;
113114
}
114115
llvm_unreachable("Improper attribute.");
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: llc -O3 -o %t -filetype=obj %s
2+
; RUN: llvm-dwarfdump %t | FileCheck %s
3+
4+
; based on clang++ output for `int *alloc_int() { return new int; }`
5+
6+
7+
target triple = "x86_64-unknown-linux-gnu"
8+
9+
define dso_local ptr @alloc_int() !dbg !3 {
10+
; CHECK: DW_TAG_subprogram
11+
entry:
12+
%call = call ptr @alloc(i64 noundef 4), !heapallocsite !7
13+
; CHECK: DW_TAG_GNU_call_site
14+
; CHECK: DW_AT_LLVM_alloc_type ([[ALLOCSITE:.*]])
15+
ret ptr %call
16+
}
17+
18+
; CHECK: {{.*}}[[ALLOCSITE]]: DW_TAG_base_type
19+
; CHECK: DW_AT_name ("int")
20+
21+
declare dso_local ptr @alloc(i64 noundef)
22+
23+
!llvm.dbg.cu = !{!0}
24+
!llvm.module.flags = !{!2}
25+
26+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, emissionKind: FullDebug)
27+
!1 = !DIFile(filename: "a.cpp", directory: "/")
28+
!2 = !{i32 2, !"Debug Info Version", i32 3}
29+
!3 = distinct !DISubprogram(name: "alloc_int", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !0)
30+
!4 = !DISubroutineType(types: !5)
31+
!5 = !{!6}
32+
!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
33+
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

0 commit comments

Comments
 (0)