diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index 48b33478d5045..b561125fe37a4 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -625,6 +625,9 @@ HANDLE_DW_AT(0x3e0a, LLVM_ptrauth_authentication_mode, 0, LLVM) HANDLE_DW_AT(0x3e0b, LLVM_num_extra_inhabitants, 0, LLVM) HANDLE_DW_AT(0x3e0c, LLVM_stmt_sequence, 0, LLVM) HANDLE_DW_AT(0x3e0d, LLVM_coro_suspend_idx, 0, LLVM) +// The DWARF v6 working draft defines DW_AT_alloc_type; use this LLVM-private ID +// until that is released as an official standard. +HANDLE_DW_AT(0x3e0e, LLVM_alloc_type, 0, LLVM) // Apple extensions. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index f9d7e763e8890..67f526fe91464 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1292,12 +1292,10 @@ DwarfCompileUnit::getDwarf5OrGNULocationAtom(dwarf::LocationAtom Loc) const { } } -DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE, - const DISubprogram *CalleeSP, - bool IsTail, - const MCSymbol *PCAddr, - const MCSymbol *CallAddr, - unsigned CallReg) { +DIE &DwarfCompileUnit::constructCallSiteEntryDIE( + DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail, + const MCSymbol *PCAddr, const MCSymbol *CallAddr, unsigned CallReg, + DIType *AllocSiteTy) { // Insert a call site entry DIE within ScopeDIE. DIE &CallSiteDIE = createAndAddDIE(getDwarf5OrGNUTag(dwarf::DW_TAG_call_site), ScopeDIE, nullptr); @@ -1306,7 +1304,7 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE, // Indirect call. addAddress(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_target), MachineLocation(CallReg)); - } else { + } else if (CalleeSP) { DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP); assert(CalleeDIE && "Could not create DIE for call site entry origin"); if (AddLinkageNamesToDeclCallOriginsForTuning(DD) && @@ -1351,6 +1349,9 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_return_pc), PCAddr); } + if (AllocSiteTy) + addType(CallSiteDIE, AllocSiteTy, dwarf::DW_AT_LLVM_alloc_type); + return CallSiteDIE; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 09be22ce35e36..c2f6ca0913818 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -289,7 +289,8 @@ class DwarfCompileUnit final : public DwarfUnit { /// the \p CallReg is set to 0. DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP, bool IsTail, const MCSymbol *PCAddr, - const MCSymbol *CallAddr, unsigned CallReg); + const MCSymbol *CallAddr, unsigned CallReg, + DIType *AllocSiteTy); /// 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 diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5ae2d2a3958bd..c27f100775625 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -936,6 +936,8 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, if (MI.hasDelaySlot() && !delaySlotSupported(*&MI)) return; + DIType *AllocSiteTy = dyn_cast_or_null(MI.getHeapAllocMarker()); + // 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. @@ -950,23 +952,23 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, PhysRegCalleeOperand = PhysRegCalleeOperand && MCOI.OperandType == MCOI::OPERAND_REGISTER; } - if (!CalleeOp.isGlobal() && !PhysRegCalleeOperand) - continue; unsigned CallReg = 0; const DISubprogram *CalleeSP = nullptr; const Function *CalleeDecl = nullptr; if (PhysRegCalleeOperand) { - CallReg = CalleeOp.getReg(); - if (!CallReg) - continue; - } else { + CallReg = CalleeOp.getReg(); // might be zero + } else if (CalleeOp.isGlobal()) { CalleeDecl = dyn_cast(CalleeOp.getGlobal()); - if (!CalleeDecl || !CalleeDecl->getSubprogram()) - continue; - CalleeSP = CalleeDecl->getSubprogram(); + if (CalleeDecl) + CalleeSP = CalleeDecl->getSubprogram(); // might be nullptr } + // Omit DIE if we can't tell where the call goes *and* we don't want to + // add metadata to it. + if (CalleeSP == nullptr && CallReg == 0 && AllocSiteTy == nullptr) + continue; + // TODO: Omit call site entries for runtime calls (objc_msgSend, etc). bool IsTail = TII->isTailCall(MI); @@ -1000,7 +1002,7 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, << (IsTail ? " [IsTail]" : "") << "\n"); DIE &CallSiteDIE = CU.constructCallSiteEntryDIE( - ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg); + ScopeDIE, CalleeSP, IsTail, PCAddr, CallAddr, CallReg, AllocSiteTy); // Optionally emit call-site-param debug info. if (emitDebugEntryValues()) { diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index 6ddb12ba04349..8052773812a2c 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -109,6 +109,7 @@ static bool isODRAttribute(uint16_t Attr) { case dwarf::DW_AT_specification: case dwarf::DW_AT_abstract_origin: case dwarf::DW_AT_import: + case dwarf::DW_AT_LLVM_alloc_type: return true; } llvm_unreachable("Improper attribute."); diff --git a/llvm/test/DebugInfo/X86/DW_AT_alloc_type.ll b/llvm/test/DebugInfo/X86/DW_AT_alloc_type.ll new file mode 100644 index 0000000000000..33028f2234ceb --- /dev/null +++ b/llvm/test/DebugInfo/X86/DW_AT_alloc_type.ll @@ -0,0 +1,34 @@ +; RUN: llc -O3 -o %t -filetype=obj %s +; RUN: llvm-dwarfdump %t | FileCheck %s + +; based on clang++ output for `int *alloc_int() { return new int; }` + + +target triple = "x86_64-unknown-linux-gnu" + +define dso_local ptr @alloc_int() !dbg !3 { +; CHECK: DW_TAG_subprogram +entry: + %call = call ptr @alloc(i64 noundef 4), !heapallocsite !7 +; CHECK: DW_TAG_call_site +; CHECK: DW_AT_LLVM_alloc_type ([[ALLOCSITE:.*]]) + ret ptr %call +} + +; CHECK: {{.*}}[[ALLOCSITE]]: DW_TAG_base_type +; CHECK: DW_AT_name ("int") + +declare dso_local ptr @alloc(i64 noundef) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2,!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, emissionKind: FullDebug) +!1 = !DIFile(filename: "a.cpp", directory: "/") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "alloc_int", scope: !1, file: !1, line: 1, type: !4, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !0) +!4 = !DISubroutineType(types: !5) +!5 = !{!6} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 5}