Skip to content

Commit 919d777

Browse files
committed
[clang][DebugInfo] Attach DISubprogram to additional call variants
`DISubprogram`s are attached to call sites to support various debug info features, including entry values and tail calls. Clang 9.0 (0f65168) was the first version to include this kind of call site `DISubprogram` attachment. This earlier work appears to visit only some call site variants, however. The call site attachment was added to a higher-level `EmitCall` path in Clang's code gen that is only used by some call variants. In particular, some C++ member calls use a different code gen path, which did not include this call site attachment step, and thus the debug info it triggers (e.g. call site entries) was not emitted for such calls. This moves `DISubprogram` attachment to a lower-level call emission path that is used by all call variants. Fixes #161962
1 parent 34a3488 commit 919d777

File tree

5 files changed

+47
-12
lines changed

5 files changed

+47
-12
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6277,6 +6277,21 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
62776277
pushDestroy(QualType::DK_nontrivial_c_struct, Ret.getAggregateAddress(),
62786278
RetTy);
62796279

6280+
if (CalleeDecl) {
6281+
// Generate function declaration DISuprogram in order to be used
6282+
// in debug info about call sites.
6283+
if (CGDebugInfo *DI = getDebugInfo()) {
6284+
CodeGenFunction CalleeCGF(CGM);
6285+
const GlobalDecl &CalleeGlobalDecl =
6286+
Callee.getAbstractInfo().getCalleeDecl();
6287+
CalleeCGF.CurGD = CalleeGlobalDecl;
6288+
FunctionArgList Args;
6289+
QualType ResTy = CalleeCGF.BuildFunctionArgList(CalleeGlobalDecl, Args);
6290+
DI->EmitFuncDeclForCallSite(
6291+
CI, DI->getFunctionType(CalleeDecl, ResTy, Args), CalleeGlobalDecl);
6292+
}
6293+
}
6294+
62806295
return Ret;
62816296
}
62826297

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4952,7 +4952,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
49524952

49534953
void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
49544954
QualType CalleeType,
4955-
const FunctionDecl *CalleeDecl) {
4955+
GlobalDecl CalleeGlobalDecl) {
49564956
if (!CallOrInvoke)
49574957
return;
49584958
auto *Func = dyn_cast<llvm::Function>(CallOrInvoke->getCalledOperand());
@@ -4961,6 +4961,9 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
49614961
if (Func->getSubprogram())
49624962
return;
49634963

4964+
const FunctionDecl *CalleeDecl =
4965+
cast<FunctionDecl>(CalleeGlobalDecl.getDecl());
4966+
49644967
// Do not emit a declaration subprogram for a function with nodebug
49654968
// attribute, or if call site info isn't required.
49664969
if (CalleeDecl->hasAttr<NoDebugAttr>() ||
@@ -4971,7 +4974,8 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
49714974
// create the one describing the function in order to have complete
49724975
// call site debug info.
49734976
if (!CalleeDecl->isStatic() && !CalleeDecl->isInlined())
4974-
EmitFunctionDecl(CalleeDecl, CalleeDecl->getLocation(), CalleeType, Func);
4977+
EmitFunctionDecl(CalleeGlobalDecl, CalleeDecl->getLocation(), CalleeType,
4978+
Func);
49754979
}
49764980

49774981
void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) {

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ class CGDebugInfo {
511511
/// This is needed for call site debug info.
512512
void EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
513513
QualType CalleeType,
514-
const FunctionDecl *CalleeDecl);
514+
GlobalDecl CalleeGlobalDecl);
515515

516516
/// Constructs the debug code for exiting a function.
517517
void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn);

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6632,15 +6632,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
66326632
E == MustTailCall, E->getExprLoc());
66336633

66346634
if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
6635-
// Generate function declaration DISuprogram in order to be used
6636-
// in debug info about call sites.
6637-
if (CGDebugInfo *DI = getDebugInfo()) {
6638-
FunctionArgList Args;
6639-
QualType ResTy = BuildFunctionArgList(CalleeDecl, Args);
6640-
DI->EmitFuncDeclForCallSite(LocalCallOrInvoke,
6641-
DI->getFunctionType(CalleeDecl, ResTy, Args),
6642-
CalleeDecl);
6643-
}
66446635
if (CalleeDecl->hasAttr<RestrictAttr>() ||
66456636
CalleeDecl->hasAttr<AllocSizeAttr>()) {
66466637
// Function has 'malloc' (aka. 'restrict') or 'alloc_size' attribute.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -O1 -triple x86_64-unknown_unknown -emit-llvm \
2+
// RUN: -debug-info-kind=standalone -dwarf-version=5 %s -o - | FileCheck %s
3+
4+
// Ensure both nonmember and member calls to declared function
5+
// have attached `DISubprogram`s.
6+
7+
int nonmember(int n);
8+
9+
struct S {
10+
int x;
11+
int member(int n);
12+
};
13+
14+
int main(int argc, char** argv) {
15+
struct S s = {};
16+
int a = s.member(argc);
17+
int b = nonmember(argc);
18+
return a + b;
19+
}
20+
21+
// CHECK: declare !dbg ![[SP1:[0-9]+]] noundef i32 @_ZN1S6memberEi(
22+
// CHECK: declare !dbg ![[SP2:[0-9]+]] noundef i32 @_Z9nonmemberi(
23+
24+
// CHECK: ![[SP1]] = !DISubprogram(name: "member", linkageName: "_ZN1S6memberEi"
25+
// CHECK: ![[SP2]] = !DISubprogram(name: "nonmember", linkageName: "_Z9nonmemberi"

0 commit comments

Comments
 (0)