https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/167666
>From 0bc830e2f2db510fa53ab65dc1e3d593b4cd39cf Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <[email protected]> Date: Wed, 11 Feb 2026 13:27:59 +0000 Subject: [PATCH 1/2] [clang][DebugInfo] Add call site target information in DWARF. These changes are intended to address the concern about the 'CallTargetCache' map. The map is removed by: - injecting a function declaration if one is not available at the point where the function is invoked. - always pointing the 'call_target' to the function declaraion. --- clang/lib/CodeGen/CGCall.cpp | 2 + clang/lib/CodeGen/CGDebugInfo.cpp | 23 ++++ clang/lib/CodeGen/CGDebugInfo.h | 9 ++ clang/test/DebugInfo/CXX/callsite-base.cpp | 38 ++++++ clang/test/DebugInfo/CXX/callsite-derived.cpp | 58 +++++++++ clang/test/DebugInfo/CXX/callsite-edges.cpp | 117 ++++++++++++++++++ .../clang_llvm_roundtrip/callsite-dwarf.cpp | 68 ++++++++++ llvm/include/llvm/BinaryFormat/Dwarf.def | 1 + llvm/include/llvm/CodeGen/MachineFunction.h | 6 + llvm/include/llvm/CodeGen/TargetLowering.h | 4 + llvm/include/llvm/IR/FixedMetadataKinds.def | 1 + .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 15 ++- .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 4 + llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 29 ++++- llvm/lib/CodeGen/MIRPrinter.cpp | 2 +- llvm/lib/CodeGen/MachineFunction.cpp | 3 + .../CodeGen/SelectionDAG/TargetLowering.cpp | 14 +++ llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 3 +- .../Target/AArch64/AArch64ISelLowering.cpp | 3 +- llvm/lib/Target/ARM/ARMISelLowering.cpp | 3 +- llvm/lib/Target/Mips/MipsISelLowering.cpp | 4 +- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 3 +- llvm/lib/Target/X86/X86ISelLoweringCall.cpp | 3 +- .../MIR/X86/callsite-emit-calleetypeid.ll | 8 +- 24 files changed, 398 insertions(+), 23 deletions(-) create mode 100644 clang/test/DebugInfo/CXX/callsite-base.cpp create mode 100644 clang/test/DebugInfo/CXX/callsite-derived.cpp create mode 100644 clang/test/DebugInfo/CXX/callsite-edges.cpp create mode 100644 cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 224b2997b7db4..6e06235b52dab 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -6322,6 +6322,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, DI->EmitFuncDeclForCallSite( CI, DI->getFunctionType(CalleeDecl, ResTy, Args), CalleeGlobalDecl); } + // Generate call site target information. + DI->addCallTarget(CalleeDecl, CI); } return Ret; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 5e452245ee627..19b5ed2da3e1a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4978,6 +4978,29 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, Fn->setSubprogram(SP); } +void CGDebugInfo::addCallTarget(const FunctionDecl *FD, llvm::CallBase *CI) { + if (!generateVirtualCallSite()) + return; + + if (!FD) + return; + + // Ignore method types that never can be indirect calls. + if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) || + FD->hasAttr<CUDAGlobalAttr>()) + return; + + // Record only indirect calls. + assert(CI && "Invalid Call Instruction."); + if (!CI->isIndirectCall()) + return; + + // Always get method definition. + if (llvm::DISubprogram *MD = getFunctionDeclaration(FD)) + // Attach the target metadata + CI->setMetadata(llvm::LLVMContext::MD_call_target, MD); +} + void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke, QualType CalleeType, GlobalDecl CalleeGlobalDecl) { diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 31b40f06f09d0..478306f8aea7d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -682,6 +682,9 @@ class CGDebugInfo { /// that it is supported and enabled. llvm::DINode::DIFlags getCallSiteRelatedAttrs() const; + /// Add call target information. + void addCallTarget(const FunctionDecl *FD, llvm::CallBase *CI); + private: /// Amend \p I's DebugLoc with \p Group (its source atom group) and \p /// Rank (lower nonzero rank is higher precedence). Does nothing if \p I @@ -906,6 +909,12 @@ class CGDebugInfo { /// If one exists, returns the linkage name of the specified \ /// (non-null) \c Method. Returns empty string otherwise. llvm::StringRef GetMethodLinkageName(const CXXMethodDecl *Method) const; + + /// Generate call target information. + bool generateVirtualCallSite() const { + // Check general conditions for call site generation. + return (getCallSiteRelatedAttrs() != llvm::DINode::FlagZero); + } }; /// A scoped helper to set the current debug location to the specified diff --git a/clang/test/DebugInfo/CXX/callsite-base.cpp b/clang/test/DebugInfo/CXX/callsite-base.cpp new file mode 100644 index 0000000000000..576fdacd2722f --- /dev/null +++ b/clang/test/DebugInfo/CXX/callsite-base.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \ +// RUN: -debug-info-kind=constructor -dwarf-version=5 -O1 %s \ +// RUN: -o - | FileCheck %s -check-prefix CHECK-BASE + +// Simple class with only virtual methods: inlined and not-inlined +// We check for a generated 'call_target' for: +// - 'f1', 'f2' and 'f3'. + +struct CBase { + virtual void f1(); + virtual void f2(); + virtual void f3() {} +}; +void CBase::f1() {} + +void bar(CBase *Base) { + Base->f1(); + Base->f2(); + Base->f3(); + + CBase B; + B.f1(); +} + +// CHECK-BASE: define {{.*}} @_Z3barP5CBase{{.*}} { +// CHECK-BASE: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F1_DCL:![0-9]+]] +// CHECK-BASE: call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F2_DCL:![0-9]+]] +// CHECK-BASE: call void %5{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F3_DCL:![0-9]+]] +// CHECK-BASE: call void @_ZN5CBaseC1Ev{{.*}} !dbg {{![0-9]+}} +// CHECK-BASE: call void @_ZN5CBase2f1Ev{{.*}} !dbg {{![0-9]+}} +// CHECK-BASE: } + +// CHECK-BASE: [[BASE_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType +// CHECK-BASE: [[BASE_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}containingType +// CHECK-BASE: [[BASE_F3_DCL]] = {{.*}}!DISubprogram(name: "f3", linkageName: "_ZN5CBase2f3Ev", {{.*}}containingType + +// CHECK-BASE: [[BASE_F1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}DISPFlagDefinition +// CHECK-BASE: [[BASE_F3_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f3", linkageName: "_ZN5CBase2f3Ev", {{.*}}DISPFlagDefinition diff --git a/clang/test/DebugInfo/CXX/callsite-derived.cpp b/clang/test/DebugInfo/CXX/callsite-derived.cpp new file mode 100644 index 0000000000000..3338290bdd829 --- /dev/null +++ b/clang/test/DebugInfo/CXX/callsite-derived.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \ +// RUN: -debug-info-kind=constructor -dwarf-version=5 -O1 %s \ +// RUN: -o - | FileCheck %s -check-prefix CHECK-DERIVED + +// Simple base and derived class with virtual and static methods: +// We check for: +// - a generated 'call_target' for 'f1'. +// - not generated 'call_target' for 'f3'. + +struct CBase { + virtual void f1() {} + static void f3(); +}; + +void CBase::f3() { +} + +void foo(CBase *Base) { + CBase::f3(); +} + +struct CDerived : public CBase { + void f1() {} +}; +void foo(CDerived *Derived); + +int main() { + CDerived D; + foo(&D); + + return 0; +} + +void foo(CDerived *Derived) { + Derived->f1(); +} + +// CHECK-DERIVED: define {{.*}} @_Z3fooP5CBase{{.*}} { +// CHECK-DERIVED: call void @_ZN5CBase2f3Ev{{.*}} !dbg {{![0-9]+}} +// CHECK-DERIVED: } + +// CHECK-DERIVED: define {{.*}} @main{{.*}} { +// CHECK-DERIVED: call void @_ZN8CDerivedC1Ev{{.*}} !dbg {{![0-9]+}} +// CHECK-DERIVED: call void @_Z3fooP8CDerived{{.*}} !dbg {{![0-9]+}} +// CHECK-DERIVED: } + +// CHECK-DERIVED: define {{.*}} @_ZN8CDerivedC1Ev{{.*}} { +// CHECK-DERIVED: call void @_ZN8CDerivedC2Ev{{.*}} !dbg {{![0-9]+}} +// CHECK-DERIVED: } + +// CHECK-DERIVED: define {{.*}} @_Z3fooP8CDerived{{.*}} { +// CHECK-DERIVED: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[DERIVED_F1_DCL:![0-9]+]] +// CHECK-DERIVED: } + +// CHECK-DERIVED: [[BASE_F1_DCL:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType +// CHECK-DERIVED: [[DERIVED_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN8CDerived2f1Ev", {{.*}}containingType +// CHECK-DERIVED: [[DERIVED_F1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN8CDerived2f1Ev", {{.*}}DISPFlagDefinition +// CHECK-DERIVED: [[BASE_F1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}DISPFlagDefinition diff --git a/clang/test/DebugInfo/CXX/callsite-edges.cpp b/clang/test/DebugInfo/CXX/callsite-edges.cpp new file mode 100644 index 0000000000000..ac969ba1bef83 --- /dev/null +++ b/clang/test/DebugInfo/CXX/callsite-edges.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \ +// RUN: -debug-info-kind=constructor -dwarf-version=5 -O1 %s \ +// RUN: -o - | FileCheck %s -check-prefix CHECK-EDGES + +// The following are identified edge cases involving the method being called: +// 1) Method is declared but not defined in current CU. +// 2) Pure virtual method but not defined in current CU. +// 3) Virtual method defined in a deeply nested structure hierarchy. + +//--------------------------------------------------------------------- +// 1) Method is declared but not defined in current CU - Pass. +// Generate 'call_target' metadata for 'f1' and 'f2'. +//--------------------------------------------------------------------- +struct CEmpty { + virtual void f1(); + virtual void f2(); +}; + +void CEmpty::f2() { +} + +void edge_a(CEmpty *Empty) { + Empty->f1(); + Empty->f2(); +} + +//--------------------------------------------------------------------- +// 2) Pure virtual method but not defined in current CU - Pass. +// Generate 'call_target' metadata for 'f1' and 'f2'. +//--------------------------------------------------------------------- +struct CBase { + virtual void f1() = 0; + virtual void f2(); +}; + +void CBase::f2() { +} + +void edge_b(CBase *Base) { + Base->f1(); + Base->f2(); +} + +//--------------------------------------------------------------------- +// 3) Virtual method defined in a deeply nested structure hierarchy - Pass. +// Generate 'call_target' metadata for 'd0', 'd1', 'd2' and 'd3'. +//--------------------------------------------------------------------- +struct CDeep { + struct CD1 { + struct CD2 { + struct CD3 { + virtual void d3(); + }; + + CD3 D3; + virtual void d2(); + }; + + CD2 D2; + virtual void d1(); + }; + + CD1 D1; + virtual void d0(); +}; + +void CDeep::d0() {} +void CDeep::CD1::d1() {} +void CDeep::CD1::CD2::d2() {} +void CDeep::CD1::CD2::CD3::d3() {} + +void edge_c(CDeep *Deep) { + Deep->d0(); + + CDeep::CD1 *D1 = &Deep->D1; + D1->d1(); + + CDeep::CD1::CD2 *D2 = &D1->D2; + D2->d2(); + + CDeep::CD1::CD2::CD3 *D3 = &D2->D3; + D3->d3(); +} + +// CHECK-EDGES: define {{.*}} @_Z6edge_aP6CEmpty{{.*}} { +// CHECK-EDGES: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CEMPTY_F1_DCL:![0-9]+]] +// CHECK-EDGES: call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[CEMPTY_F2_DCL:![0-9]+]] +// CHECK-EDGES: } + +// CHECK-EDGES: define {{.*}} @_Z6edge_bP5CBase{{.*}} { +// CHECK-EDGES: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CBASE_F1_DCL:![0-9]+]] +// CHECK-EDGES: call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[CBASE_F2_DCL:![0-9]+]] +// CHECK-EDGES: } + +// CHECK-EDGES: define {{.*}} @_Z6edge_cP5CDeep{{.*}} { +// CHECK-EDGES: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D0_DCL:![0-9]+]] +// CHECK-EDGES: call void %4{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D1_DCL:![0-9]+]] +// CHECK-EDGES: call void %7{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D2_DCL:![0-9]+]] +// CHECK-EDGES: call void %10{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D3_DCL:![0-9]+]] +// CHECK-EDGES: } + +// CHECK-EDGES: [[CDEEP_D3_DCL]] = {{.*}}!DISubprogram(name: "d3", linkageName: "_ZN5CDeep3CD13CD23CD32d3Ev", {{.*}}containingType +// CHECK-EDGES: [[CDEEP_D2_DCL]] = {{.*}}!DISubprogram(name: "d2", linkageName: "_ZN5CDeep3CD13CD22d2Ev", {{.*}}containingType +// CHECK-EDGES: [[CDEEP_D1_DCL]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN5CDeep3CD12d1Ev", {{.*}}containingType +// CHECK-EDGES: [[CDEEP_D0_DCL]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN5CDeep2d0Ev", {{.*}}containingType + +// CHECK-EDGES: [[CBASE_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType +// CHECK-EDGES: [[CBASE_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}containingType +// CHECK-EDGES: [[CEMPTY_F2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN6CEmpty2f2Ev", {{.*}}DISPFlagDefinition +// CHECK-EDGES: [[CEMPTY_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN6CEmpty2f2Ev", {{.*}}containingType +// CHECK-EDGES: [[CEMPTY_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN6CEmpty2f1Ev", {{.*}}containingType +// CHECK-EDGES: [[CBASE_F2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}DISPFlagDefinition + +// CHECK-EDGES: [[CDEEP_D0_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN5CDeep2d0Ev", {{.*}}DISPFlagDefinition +// CHECK-EDGES: [[CDEEP_D1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN5CDeep3CD12d1Ev", {{.*}}DISPFlagDefinition +// CHECK-EDGES: [[CDEEP_D2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d2", linkageName: "_ZN5CDeep3CD13CD22d2Ev", {{.*}}DISPFlagDefinition +// CHECK-EDGES: [[CDEEP_D3_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d3", linkageName: "_ZN5CDeep3CD13CD23CD32d3Ev", {{.*}}DISPFlagDefinition diff --git a/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp b/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp new file mode 100644 index 0000000000000..269bb04f8ffe6 --- /dev/null +++ b/cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/callsite-dwarf.cpp @@ -0,0 +1,68 @@ +// RUN: %clang --target=x86_64-unknown-linux -c -g -O1 %s -o - | \ +// RUN: llvm-dwarfdump --debug-info - | FileCheck %s --check-prefix=CHECK + +// Simple base and derived class with virtual: +// We check for a generated 'DW_AT_LLVM_virtual_call_origin' for 'foo', that +// corresponds to the 'call_target' metadata added to the indirect call +// instruction. + +struct CBaseOne { + virtual void foo(int &); +}; + +struct CDerivedOne : CBaseOne { + void foo(int &); +}; + +void CDerivedOne::foo(int &) {} + +struct CBaseTwo { + CDerivedOne *DerivedOne; +}; + +struct CDerivedTwo : CBaseTwo { + void bar(int &); +}; + +void CDerivedTwo::bar(int &j) { DerivedOne->foo(j); } + +// The IR generated looks like: +// +// define dso_local void @_ZN11CDerivedTwo3barERi(...) !dbg !40 { +// entry: +// .. +// %vtable = load ptr, ptr %0, align 8 +// %vfn = getelementptr inbounds ptr, ptr %vtable, i64 0 +// %2 = load ptr, ptr %vfn, align 8 +// call void %2(...), !dbg !65, !call_target !25 +// ret void +// } +// +// !25 = !DISubprogram(name: "foo", linkageName: "_ZN11CDerivedOne3fooERi", ...) +// !40 = !DISubprogram(name: "bar", linkageName: "_ZN11CDerivedTwo3barERi", ...) +// !65 = !DILocation(line: 25, column: 15, scope: !40) + +// CHECK: DW_TAG_compile_unit +// CHECK: DW_TAG_structure_type +// CHECK: DW_AT_name ("CDerivedOne") +// CHECK: [[FOO_DCL:0x[a-f0-9]+]]: DW_TAG_subprogram +// CHECK: DW_AT_name ("foo") +// CHECK: DW_TAG_structure_type +// CHECK: DW_AT_name ("CBaseOne") +// CHECK: [[FOO_DEF:0x[a-f0-9]+]]: DW_TAG_subprogram +// CHECK: DW_AT_call_all_calls (true) +// CHECK: DW_AT_specification ([[FOO_DCL]] "{{.*}}foo{{.*}}") +// CHECK: DW_TAG_structure_type +// CHECK: DW_AT_name ("CDerivedTwo") +// CHECK: DW_TAG_subprogram +// CHECK: DW_AT_name ("bar") +// CHECK: DW_TAG_structure_type +// CHECK: DW_AT_name ("CBaseTwo") +// CHECK: DW_TAG_subprogram +// CHECK: DW_AT_call_all_calls (true) +// CHECK: DW_AT_specification (0x{{.*}} "{{.*}}bar{{.*}}") +// CHECK: DW_TAG_call_site +// CHECK: DW_AT_call_target_clobbered (DW_OP_reg0 RAX) +// CHECK: DW_AT_call_tail_call (true) +// CHECK: DW_AT_call_pc (0x{{.*}}) +// CHECK: DW_AT_LLVM_virtual_call_origin ([[FOO_DCL]] "{{.*}}foo{{.*}}") diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index 75f1061c471c6..50b83884c851a 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -647,6 +647,7 @@ HANDLE_DW_AT(0x3e10, LLVM_address_space, 0, LLVM) HANDLE_DW_AT(0x3e11, LLVM_lanes, 0, LLVM) HANDLE_DW_AT(0x3e12, LLVM_lane_pc, 0, LLVM) HANDLE_DW_AT(0x3e13, LLVM_vector_size, 0, LLVM) +HANDLE_DW_AT(0x3e14, LLVM_virtual_call_origin, 0, LLVM) // https://llvm.org/docs/AMDGPUUsage.html#address-space-identifier HANDLE_DW_ASPACE(0x0, none) diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index edb8963ce42b6..a548151b940a6 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -526,11 +526,17 @@ class LLVM_ABI MachineFunction { /// Callee type ids. SmallVector<ConstantInt *, 4> CalleeTypeIds; + /// 'call_target' metadata for the DISubprogram. It is the declaration + /// or definition of the target function and might be indirect. + MDNode *MD = nullptr; + CallSiteInfo() = default; /// Extracts the numeric type id from the CallBase's callee_type Metadata, /// and sets CalleeTypeIds. This is used as type id for the indirect call in /// the call graph section. + /// Extracts the MDNode from the CallBase's call_target Metadata to be used + /// during the construction of the debug info call site entries. LLVM_ABI CallSiteInfo(const CallBase &CB); }; diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index f6d5578412d1e..941e0a19ebb49 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -5930,6 +5930,10 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase { LoadSDNode *OriginalLoad, SelectionDAG &DAG) const; +protected: + void setTypeIdForCallsiteInfo(const CallBase *CB, MachineFunction &MF, + MachineFunction::CallSiteInfo &CSInfo) const; + private: SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, const SDLoc &DL, DAGCombinerInfo &DCI) const; diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def index 98129985714b2..0d79677d7079e 100644 --- a/llvm/include/llvm/IR/FixedMetadataKinds.def +++ b/llvm/include/llvm/IR/FixedMetadataKinds.def @@ -59,3 +59,4 @@ LLVM_FIXED_MD_KIND(MD_captures, "captures", 44) LLVM_FIXED_MD_KIND(MD_alloc_token, "alloc_token", 45) LLVM_FIXED_MD_KIND(MD_implicit_ref, "implicit.ref", 46) LLVM_FIXED_MD_KIND(MD_nofpclass, "nofpclass", 47) +LLVM_FIXED_MD_KIND(MD_call_target, "call_target", 48) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index e87d3f3ee02a0..d2389f06e23db 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -1349,11 +1349,7 @@ DIE &DwarfCompileUnit::constructCallSiteEntryDIE( } else if (CalleeSP) { DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP, CalleeF); assert(CalleeDIE && "Could not create DIE for call site entry origin"); - if (AddLinkageNamesToDeclCallOriginsForTuning(DD) && - !CalleeSP->isDefinition() && - !CalleeDIE->findAttribute(dwarf::DW_AT_linkage_name)) { - addLinkageName(*CalleeDIE, CalleeSP->getLinkageName()); - } + addLinkageNamesToDeclarations(DD, CalleeSP, CalleeDIE); addDIEEntry(CallSiteDIE, getDwarf5OrGNUAttr(dwarf::DW_AT_call_origin), *CalleeDIE); @@ -1891,3 +1887,12 @@ DIE *DwarfCompileUnit::getOrCreateSubprogramDIE(const DISubprogram *SP, return DwarfUnit::getOrCreateSubprogramDIE(SP, F, Minimal); } + +void DwarfCompileUnit::addLinkageNamesToDeclarations( + const DwarfDebug *DD, const DISubprogram *CalleeSP, DIE *CalleeDIE) { + if (AddLinkageNamesToDeclCallOriginsForTuning(DD) && + !CalleeSP->isDefinition() && + !CalleeDIE->findAttribute(dwarf::DW_AT_linkage_name)) { + addLinkageName(*CalleeDIE, CalleeSP->getLinkageName()); + } +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 04d4556c3ce52..15becc77baaee 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -436,6 +436,10 @@ class DwarfCompileUnit final : public DwarfUnit { void addBaseTypeRef(DIEValueList &Die, int64_t Idx); MDNodeSetVector &getDeferredLocalDecls() { return DeferredLocalDecls; } + + void addLinkageNamesToDeclarations(const DwarfDebug *DD, + const DISubprogram *CalleeSP, + DIE *CalleeDIE); }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f8c2c753b91ce..7b811f677fe77 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -955,6 +955,30 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, return true; }; + // Create call_target connections for indirect calls. + auto addCallSiteTargetForIndirectCalls = [&](const MachineInstr *MI, + DIE &CallSiteDIE) { + const MachineFunction *MF = MI->getMF(); + const auto &CalleesMap = MF->getCallSitesInfo(); + auto CSInfo = CalleesMap.find(MI); + // Get the information for the call instruction. + if (CSInfo == CalleesMap.end() || !CSInfo->second.MD) + return; + + MDNode *MD = CSInfo->second.MD; + // Add DW_AT_LLVM_virtual_call_origin with the 'call_target' metadata. + assert(!CallSiteDIE.findAttribute(dwarf::DW_AT_LLVM_virtual_call_origin) && + "DW_AT_LLVM_virtual_call_origin already exists"); + const DISubprogram *CalleeSP = dyn_cast<DISubprogram>(MD); + DIE *CalleeDIE = CU.getOrCreateSubprogramDIE(CalleeSP, nullptr); + assert(CalleeDIE && "Could not create DIE for call site entry origin"); + CU.addDIEEntry(CallSiteDIE, + CU.getDwarf5OrGNUAttr(dwarf::DW_AT_LLVM_virtual_call_origin), + *CalleeDIE); + // Add DW_AT_linkage_name to the method declaration if needed. + CU.addLinkageNamesToDeclarations(this, CalleeSP, CalleeDIE); + }; + // Emit call site entries for each call or tail call in the function. for (const MachineBasicBlock &MBB : MF) { for (const MachineInstr &MI : MBB.instrs()) { @@ -1052,6 +1076,9 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, ScopeDIE, CalleeSP, CalleeDecl, IsTail, PCAddr, CallAddr, CallTarget, Offset, AllocSiteTy); + if (CallTarget.getReg()) + addCallSiteTargetForIndirectCalls(TopLevelCallMI, CallSiteDIE); + // Optionally emit call-site-param debug info. if (emitDebugEntryValues()) { ParamSet Params; @@ -1460,7 +1487,7 @@ void DwarfDebug::finalizeModuleInfo() { TLOF.getDwarfMacinfoSection()->getBeginSymbol()); } } - } + } // Emit all frontend-produced Skeleton CUs, i.e., Clang modules. for (auto *CUNode : MMI->getModule()->debug_compile_units()) diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 9a48a0062549a..93c20394cf98c 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -541,7 +541,7 @@ static void convertCallSiteObjects(yaml::MachineFunction &YMF, std::distance(CallI->getParent()->instr_begin(), CallI); YmlCS.CallLocation = CallLocation; - auto [ArgRegPairs, CalleeTypeIds] = CallSiteInfo; + auto [ArgRegPairs, CalleeTypeIds, MD] = CallSiteInfo; // Construct call arguments and theirs forwarding register info. for (auto ArgReg : ArgRegPairs) { yaml::CallSiteInfo::ArgRegPair YmlArgReg; diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index fb35c7e62dad6..1bcd7b401a3d4 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -700,6 +700,9 @@ bool MachineFunction::needsFrameMoves() const { } MachineFunction::CallSiteInfo::CallSiteInfo(const CallBase &CB) { + if (MDNode *Node = CB.getMetadata(llvm::LLVMContext::MD_call_target)) + MD = Node; + // Numeric callee_type ids are only for indirect calls. if (!CB.isIndirectCall()) return; diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index e4b4d80896fa7..fc7c57f24e41f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -12763,3 +12763,17 @@ SDValue TargetLowering::scalarizeExtractedVectorLoad(EVT ResultVT, return Load; } + +// Set type id for call site info and metadata 'call_target'. +// We are filtering for: +// a) The call-graph-section use case that wants to know about indirect +// calls, or +// b) We want to annotate indirect calls. +void TargetLowering::setTypeIdForCallsiteInfo( + const CallBase *CB, MachineFunction &MF, + MachineFunction::CallSiteInfo &CSInfo) const { + if (CB && CB->isIndirectCall() && + (MF.getTarget().Options.EmitCallGraphSection || + MF.getTarget().Options.EmitCallSiteInfo)) + CSInfo = MachineFunction::CallSiteInfo(*CB); +} diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index cd8a2b305a0f9..f8357ed216f5f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -246,7 +246,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, // having both the raw value and the pretty-printed value is // interesting. These attributes are handled below. if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin || - Attr == DW_AT_call_origin || Attr == DW_AT_import) { + Attr == DW_AT_call_origin || Attr == DW_AT_import || + Attr == DW_AT_LLVM_virtual_call_origin) { if (const char *Name = Die.getAttributeValueAsReferencedDie(FormValue).getName( DINameKind::LinkageName)) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 66c22db0491d1..ba9cebd3deda9 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9928,8 +9928,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, RetCCInfo.AnalyzeCallResult(Ins, RetCC); // Set type id for call site info. - if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall()) - CSInfo = MachineFunction::CallSiteInfo(*CB); + setTypeIdForCallsiteInfo(CB, MF, CSInfo); // Check callee args/returns for SVE registers and set calling convention // accordingly. diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index f9ce14b079826..c964dd912b777 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2056,8 +2056,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, GuardWithBTI = AFI->branchTargetEnforcement(); // Set type id for call site info. - if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall()) - CSInfo = MachineFunction::CallSiteInfo(*CB); + setTypeIdForCallsiteInfo(CB, MF, CSInfo); // Determine whether this is a non-secure function call. if (CLI.CB && CLI.CB->getAttributes().hasFnAttr("cmse_nonsecure_call")) diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index c920e912f49ac..9d05ab1b83417 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -3342,9 +3342,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Call site info for function parameters tracking and call base type info. MachineFunction::CallSiteInfo CSInfo; + // Set type id for call site info. - if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall()) - CSInfo = MachineFunction::CallSiteInfo(*CB); + setTypeIdForCallsiteInfo(CB, MF, CSInfo); // Check if it's really possible to do a tail call. // For non-musttail calls, restrict to functions that won't require $gp diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 4d38ee354d86f..91dde57f431b8 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -24481,8 +24481,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI, MachineFunction::CallSiteInfo CSInfo; // Set type id for call site info. - if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall()) - CSInfo = MachineFunction::CallSiteInfo(*CB); + setTypeIdForCallsiteInfo(CB, MF, CSInfo); // Analyze the operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp index 92348689f57f0..c0e120dc30b86 100644 --- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp +++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp @@ -2078,8 +2078,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, report_fatal_error("X86 interrupts may not be called directly"); // Set type id for call site info. - if (MF.getTarget().Options.EmitCallGraphSection && CB && CB->isIndirectCall()) - CSInfo = MachineFunction::CallSiteInfo(*CB); + setTypeIdForCallsiteInfo(CB, MF, CSInfo); if (IsIndirectCall && !IsWin64 && M->getModuleFlag("import-call-optimization")) diff --git a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll index 3f7590adf9182..fe1980e3f5605 100644 --- a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll @@ -32,14 +32,13 @@ ;; Test printer and parser with -emit-call-site-info only. ;; Test printer. -;; Verify that fwdArgRegs is set, calleeTypeIds is not set. +;; Verify that fwdArgRegs and calleeTypeIds are set. ; RUN: llc -mtriple=x86_64 -emit-call-site-info %s -stop-after=finalize-isel -o %t2.mir ; RUN: cat %t2.mir | FileCheck %s --check-prefix=PRINTER_CSI ; PRINTER_CSI: name: main ; PRINTER_CSI: callSites: ; PRINTER_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: -; PRINTER_CSI-NEXT: { arg: 0, reg: {{.*}} } -; PRINTER_CSI-NOT: calleeTypeIds: +; PRINTER_CSI-NEXT: { arg: 0, reg: {{.*}} }, calleeTypeIds: ;; Test parser. @@ -49,8 +48,7 @@ ; PARSER_CSI: name: main ; PARSER_CSI: callSites: ; PARSER_CSI-NEXT: - { bb: {{.*}}, offset: {{.*}}, fwdArgRegs: -; PARSER_CSI-NEXT: { arg: 0, reg: {{.*}} } -; PARSER_CSI-NOT: calleeTypeIds: +; PARSER_CSI-NEXT: { arg: 0, reg: {{.*}} }, calleeTypeIds: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Test printer and parser with both -emit-call-site-info and --call-graph-section. >From db78449ff8d35c26b557e6a9219722abc0571645 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <[email protected]> Date: Mon, 16 Feb 2026 13:55:22 +0000 Subject: [PATCH 2/2] [clang][DebugInfo] Add call site target information in DWARF. Address reviewer feedback: - Rename 'MD' variable to a better descriptive name. - Remove redundant code for indirect call check. - Reduce nesting level in 'callsite-edges' test case. - Improve comments and add check for CBase type definition. --- clang/lib/CodeGen/CGDebugInfo.cpp | 5 --- clang/test/DebugInfo/CXX/callsite-base.cpp | 16 +++++-- clang/test/DebugInfo/CXX/callsite-edges.cpp | 50 ++++++--------------- llvm/include/llvm/CodeGen/MachineFunction.h | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 6 +-- llvm/lib/CodeGen/MachineFunction.cpp | 2 +- 6 files changed, 31 insertions(+), 50 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 19b5ed2da3e1a..6aa422101d4aa 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -4985,11 +4985,6 @@ void CGDebugInfo::addCallTarget(const FunctionDecl *FD, llvm::CallBase *CI) { if (!FD) return; - // Ignore method types that never can be indirect calls. - if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) || - FD->hasAttr<CUDAGlobalAttr>()) - return; - // Record only indirect calls. assert(CI && "Invalid Call Instruction."); if (!CI->isIndirectCall()) diff --git a/clang/test/DebugInfo/CXX/callsite-base.cpp b/clang/test/DebugInfo/CXX/callsite-base.cpp index 576fdacd2722f..cf26d62a03c0b 100644 --- a/clang/test/DebugInfo/CXX/callsite-base.cpp +++ b/clang/test/DebugInfo/CXX/callsite-base.cpp @@ -1,10 +1,16 @@ // RUN: %clang_cc1 -triple=x86_64-linux -disable-llvm-passes -emit-llvm \ -// RUN: -debug-info-kind=constructor -dwarf-version=5 -O1 %s \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 -O1 %s \ // RUN: -o - | FileCheck %s -check-prefix CHECK-BASE // Simple class with only virtual methods: inlined and not-inlined -// We check for a generated 'call_target' for: -// - 'f1', 'f2' and 'f3'. +// +// The following three scenarios are considered: +// - out-of-line defined virtual member function (f1) +// - declared-but-not-defined virtual member function (f2) +// - inline defined virtual member function (f3) +// +// 1) We check for a generated 'call_target' for: 'f1', 'f2' and 'f3'. +// 2) Check that the 'CBase' type is defined. struct CBase { virtual void f1(); @@ -18,11 +24,15 @@ void bar(CBase *Base) { Base->f2(); Base->f3(); + // Because this will instantiate the ctor, the CBase type should be defined. CBase B; B.f1(); } +// CHECK-BASE: %struct.CBase = type { ptr } + // CHECK-BASE: define {{.*}} @_Z3barP5CBase{{.*}} { +// CHECK-BASE: alloca %struct.CBase // CHECK-BASE: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F1_DCL:![0-9]+]] // CHECK-BASE: call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F2_DCL:![0-9]+]] // CHECK-BASE: call void %5{{.*}} !dbg {{![0-9]+}}, !call_target [[BASE_F3_DCL:![0-9]+]] diff --git a/clang/test/DebugInfo/CXX/callsite-edges.cpp b/clang/test/DebugInfo/CXX/callsite-edges.cpp index ac969ba1bef83..812cfc1fb4cf2 100644 --- a/clang/test/DebugInfo/CXX/callsite-edges.cpp +++ b/clang/test/DebugInfo/CXX/callsite-edges.cpp @@ -45,18 +45,8 @@ void edge_b(CBase *Base) { // 3) Virtual method defined in a deeply nested structure hierarchy - Pass. // Generate 'call_target' metadata for 'd0', 'd1', 'd2' and 'd3'. //--------------------------------------------------------------------- -struct CDeep { +struct CD0 { struct CD1 { - struct CD2 { - struct CD3 { - virtual void d3(); - }; - - CD3 D3; - virtual void d2(); - }; - - CD2 D2; virtual void d1(); }; @@ -64,22 +54,14 @@ struct CDeep { virtual void d0(); }; -void CDeep::d0() {} -void CDeep::CD1::d1() {} -void CDeep::CD1::CD2::d2() {} -void CDeep::CD1::CD2::CD3::d3() {} +void CD0::d0() {} +void CD0::CD1::d1() {} -void edge_c(CDeep *Deep) { - Deep->d0(); +void edge_c(CD0 *D0) { + D0->d0(); - CDeep::CD1 *D1 = &Deep->D1; + CD0::CD1 *D1 = &D0->D1; D1->d1(); - - CDeep::CD1::CD2 *D2 = &D1->D2; - D2->d2(); - - CDeep::CD1::CD2::CD3 *D3 = &D2->D3; - D3->d3(); } // CHECK-EDGES: define {{.*}} @_Z6edge_aP6CEmpty{{.*}} { @@ -92,17 +74,13 @@ void edge_c(CDeep *Deep) { // CHECK-EDGES: call void %3{{.*}} !dbg {{![0-9]+}}, !call_target [[CBASE_F2_DCL:![0-9]+]] // CHECK-EDGES: } -// CHECK-EDGES: define {{.*}} @_Z6edge_cP5CDeep{{.*}} { -// CHECK-EDGES: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D0_DCL:![0-9]+]] -// CHECK-EDGES: call void %4{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D1_DCL:![0-9]+]] -// CHECK-EDGES: call void %7{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D2_DCL:![0-9]+]] -// CHECK-EDGES: call void %10{{.*}} !dbg {{![0-9]+}}, !call_target [[CDEEP_D3_DCL:![0-9]+]] +// CHECK-EDGES: define {{.*}} @_Z6edge_cP3CD0{{.*}} { +// CHECK-EDGES: call void %1{{.*}} !dbg {{![0-9]+}}, !call_target [[CD0_D0_DCL:![0-9]+]] +// CHECK-EDGES: call void %4{{.*}} !dbg {{![0-9]+}}, !call_target [[CD0_D1_DCL:![0-9]+]] // CHECK-EDGES: } -// CHECK-EDGES: [[CDEEP_D3_DCL]] = {{.*}}!DISubprogram(name: "d3", linkageName: "_ZN5CDeep3CD13CD23CD32d3Ev", {{.*}}containingType -// CHECK-EDGES: [[CDEEP_D2_DCL]] = {{.*}}!DISubprogram(name: "d2", linkageName: "_ZN5CDeep3CD13CD22d2Ev", {{.*}}containingType -// CHECK-EDGES: [[CDEEP_D1_DCL]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN5CDeep3CD12d1Ev", {{.*}}containingType -// CHECK-EDGES: [[CDEEP_D0_DCL]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN5CDeep2d0Ev", {{.*}}containingType +// CHECK-EDGES: [[CD0_D1_DCL]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN3CD03CD12d1Ev", {{.*}}containingType +// CHECK-EDGES: [[CD0_D0_DCL]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN3CD02d0Ev", {{.*}}containingType // CHECK-EDGES: [[CBASE_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN5CBase2f1Ev", {{.*}}containingType // CHECK-EDGES: [[CBASE_F2_DCL]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}containingType @@ -111,7 +89,5 @@ void edge_c(CDeep *Deep) { // CHECK-EDGES: [[CEMPTY_F1_DCL]] = {{.*}}!DISubprogram(name: "f1", linkageName: "_ZN6CEmpty2f1Ev", {{.*}}containingType // CHECK-EDGES: [[CBASE_F2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "f2", linkageName: "_ZN5CBase2f2Ev", {{.*}}DISPFlagDefinition -// CHECK-EDGES: [[CDEEP_D0_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN5CDeep2d0Ev", {{.*}}DISPFlagDefinition -// CHECK-EDGES: [[CDEEP_D1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN5CDeep3CD12d1Ev", {{.*}}DISPFlagDefinition -// CHECK-EDGES: [[CDEEP_D2_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d2", linkageName: "_ZN5CDeep3CD13CD22d2Ev", {{.*}}DISPFlagDefinition -// CHECK-EDGES: [[CDEEP_D3_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d3", linkageName: "_ZN5CDeep3CD13CD23CD32d3Ev", {{.*}}DISPFlagDefinition +// CHECK-EDGES: [[CD0_D0_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d0", linkageName: "_ZN3CD02d0Ev", {{.*}}DISPFlagDefinition +// CHECK-EDGES: [[CD0_D1_DEF:![0-9]+]] = {{.*}}!DISubprogram(name: "d1", linkageName: "_ZN3CD03CD12d1Ev", {{.*}}DISPFlagDefinition diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index a548151b940a6..26b6c457a45ba 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -528,7 +528,7 @@ class LLVM_ABI MachineFunction { /// 'call_target' metadata for the DISubprogram. It is the declaration /// or definition of the target function and might be indirect. - MDNode *MD = nullptr; + MDNode *CallTarget = nullptr; CallSiteInfo() = default; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 7b811f677fe77..80c16b103149d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -962,14 +962,14 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, const auto &CalleesMap = MF->getCallSitesInfo(); auto CSInfo = CalleesMap.find(MI); // Get the information for the call instruction. - if (CSInfo == CalleesMap.end() || !CSInfo->second.MD) + if (CSInfo == CalleesMap.end() || !CSInfo->second.CallTarget) return; - MDNode *MD = CSInfo->second.MD; + MDNode *CallTarget = CSInfo->second.CallTarget; // Add DW_AT_LLVM_virtual_call_origin with the 'call_target' metadata. assert(!CallSiteDIE.findAttribute(dwarf::DW_AT_LLVM_virtual_call_origin) && "DW_AT_LLVM_virtual_call_origin already exists"); - const DISubprogram *CalleeSP = dyn_cast<DISubprogram>(MD); + const DISubprogram *CalleeSP = dyn_cast<DISubprogram>(CallTarget); DIE *CalleeDIE = CU.getOrCreateSubprogramDIE(CalleeSP, nullptr); assert(CalleeDIE && "Could not create DIE for call site entry origin"); CU.addDIEEntry(CallSiteDIE, diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index 1bcd7b401a3d4..fe876fe4dc3e8 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -701,7 +701,7 @@ bool MachineFunction::needsFrameMoves() const { MachineFunction::CallSiteInfo::CallSiteInfo(const CallBase &CB) { if (MDNode *Node = CB.getMetadata(llvm::LLVMContext::MD_call_target)) - MD = Node; + CallTarget = Node; // Numeric callee_type ids are only for indirect calls. if (!CB.isIndirectCall()) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
