Skip to content

Commit 9b921c2

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 da6424c commit 9b921c2

File tree

6 files changed

+60
-18
lines changed

6 files changed

+60
-18
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: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,12 +1292,10 @@ DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const {
12921292
}
12931293
}
12941294

1295-
DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
1296-
const DISubprogram *CalleeSP,
1297-
bool IsTail,
1298-
const MCSymbol *PCAddr,
1299-
const MCSymbol *CallAddr,
1300-
unsigned CallReg) {
1295+
DIE &DwarfCompileUnit::constructCallSiteEntryDIE(
1296+
DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail,
1297+
const MCSymbol *PCAddr, const MCSymbol *CallAddr, unsigned CallReg,
1298+
DIType *AllocSiteTy) {
13011299
// Insert a call site entry DIE within ScopeDIE.
13021300
DIE &CallSiteDIE = createAndAddDIE(getDwarf5OrGNUTag(dwarf::DW_TAG_call_site),
13031301
ScopeDIE, nullptr);
@@ -1306,7 +1304,7 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
13061304
// Indirect call.
13071305
addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target),
13081306
MachineLocation(CallReg));
1309-
} else {
1307+
} else if (CalleeSP) {
13101308
DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
13111309
assert(CalleeDIE && "Could not create DIE for call site entry origin");
13121310
if (AddLinkageNamesToDeclCallOriginsForTuning(DD) &&
@@ -1351,6 +1349,9 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
13511349
getDwarf5OrGNUAttr(dwarf::DW_AT_call_return_pc), PCAddr);
13521350
}
13531351

1352+
if (AllocSiteTy)
1353+
addType(CallSiteDIE, AllocSiteTy, dwarf::DW_AT_LLVM_alloc_type);
1354+
13541355
return CallSiteDIE;
13551356
}
13561357

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: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,8 @@ 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.
@@ -950,23 +952,23 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
950952
PhysRegCalleeOperand =
951953
PhysRegCalleeOperand && MCOI.OperandType == MCOI::OPERAND_REGISTER;
952954
}
953-
if (!CalleeOp.isGlobal() && !PhysRegCalleeOperand)
954-
continue;
955955

956956
unsigned CallReg = 0;
957957
const DISubprogram *CalleeSP = nullptr;
958958
const Function *CalleeDecl = nullptr;
959959
if (PhysRegCalleeOperand) {
960-
CallReg = CalleeOp.getReg();
961-
if (!CallReg)
962-
continue;
963-
} else {
960+
CallReg = CalleeOp.getReg(); // might be zero
961+
} else if (CalleeOp.isGlobal()) {
964962
CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
965-
if (!CalleeDecl || !CalleeDecl->getSubprogram())
966-
continue;
967-
CalleeSP = CalleeDecl->getSubprogram();
963+
if (CalleeDecl)
964+
CalleeSP = CalleeDecl->getSubprogram(); // might be nullptr
968965
}
969966

967+
// Omit DIE if we can't tell where the call goes *and* we don't want to
968+
// add metadata to it.
969+
if (CalleeSP == nullptr && CallReg == 0 && AllocSiteTy == nullptr)
970+
continue;
971+
970972
// TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
971973

972974
bool IsTail = TII->isTailCall(MI);
@@ -1000,7 +1002,7 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
10001002
<< (IsTail ? " [IsTail]" : "") << "\n");
10011003

10021004
DIE &CallSiteDIE = CU.constructCallSiteEntryDIE(
1003-
ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg);
1005+
ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg, AllocSiteTy);
10041006

10051007
// Optionally emit call-site-param debug info.
10061008
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: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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_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,!8}
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)
34+
!8 = !{i32 2, !"Dwarf Version", i32 5}

0 commit comments

Comments
 (0)