Skip to content

Commit 342e28f

Browse files
authored
[clang][DebugInfo] Attach DISubprogram to additional call variants (#166202)
`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 309729e commit 342e28f

File tree

5 files changed

+55
-17
lines changed

5 files changed

+55
-17
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "llvm/IR/Attributes.h"
3939
#include "llvm/IR/CallingConv.h"
4040
#include "llvm/IR/DataLayout.h"
41+
#include "llvm/IR/DebugInfoMetadata.h"
4142
#include "llvm/IR/InlineAsm.h"
4243
#include "llvm/IR/IntrinsicInst.h"
4344
#include "llvm/IR/Intrinsics.h"
@@ -6277,6 +6278,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
62776278
pushDestroy(QualType::DK_nontrivial_c_struct, Ret.getAggregateAddress(),
62786279
RetTy);
62796280

6281+
// Generate function declaration DISuprogram in order to be used
6282+
// in debug info about call sites.
6283+
if (CGDebugInfo *DI = getDebugInfo()) {
6284+
// Ensure call site info would actually be emitted before collecting
6285+
// further callee info.
6286+
if (CalleeDecl && !CalleeDecl->hasAttr<NoDebugAttr>() &&
6287+
DI->getCallSiteRelatedAttrs() != llvm::DINode::FlagZero) {
6288+
CodeGenFunction CalleeCGF(CGM);
6289+
const GlobalDecl &CalleeGlobalDecl =
6290+
Callee.getAbstractInfo().getCalleeDecl();
6291+
CalleeCGF.CurGD = CalleeGlobalDecl;
6292+
FunctionArgList Args;
6293+
QualType ResTy = CalleeCGF.BuildFunctionArgList(CalleeGlobalDecl, Args);
6294+
DI->EmitFuncDeclForCallSite(
6295+
CI, DI->getFunctionType(CalleeDecl, ResTy, Args), CalleeGlobalDecl);
6296+
}
6297+
}
6298+
62806299
return Ret;
62816300
}
62826301

clang/lib/CodeGen/CGDebugInfo.cpp

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

49584958
void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
49594959
QualType CalleeType,
4960-
const FunctionDecl *CalleeDecl) {
4960+
GlobalDecl CalleeGlobalDecl) {
49614961
if (!CallOrInvoke)
49624962
return;
49634963
auto *Func = dyn_cast<llvm::Function>(CallOrInvoke->getCalledOperand());
@@ -4966,6 +4966,9 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
49664966
if (Func->getSubprogram())
49674967
return;
49684968

4969+
const FunctionDecl *CalleeDecl =
4970+
cast<FunctionDecl>(CalleeGlobalDecl.getDecl());
4971+
49694972
// Do not emit a declaration subprogram for a function with nodebug
49704973
// attribute, or if call site info isn't required.
49714974
if (CalleeDecl->hasAttr<NoDebugAttr>() ||
@@ -4976,7 +4979,8 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
49764979
// create the one describing the function in order to have complete
49774980
// call site debug info.
49784981
if (!CalleeDecl->isStatic() && !CalleeDecl->isInlined())
4979-
EmitFunctionDecl(CalleeDecl, CalleeDecl->getLocation(), CalleeType, Func);
4982+
EmitFunctionDecl(CalleeGlobalDecl, CalleeDecl->getLocation(), CalleeType,
4983+
Func);
49804984
}
49814985

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

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 5 additions & 6 deletions
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);
@@ -678,6 +678,10 @@ class CGDebugInfo {
678678
/// Emit symbol for debugger that holds the pointer to the vtable.
679679
void emitVTableSymbol(llvm::GlobalVariable *VTable, const CXXRecordDecl *RD);
680680

681+
/// Return flags which enable debug info emission for call sites, provided
682+
/// that it is supported and enabled.
683+
llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;
684+
681685
private:
682686
/// Amend \p I's DebugLoc with \p Group (its source atom group) and \p
683687
/// Rank (lower nonzero rank is higher precedence). Does nothing if \p I
@@ -827,11 +831,6 @@ class CGDebugInfo {
827831
unsigned LineNo, StringRef LinkageName,
828832
llvm::GlobalVariable *Var, llvm::DIScope *DContext);
829833

830-
831-
/// Return flags which enable debug info emission for call sites, provided
832-
/// that it is supported and enabled.
833-
llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;
834-
835834
/// Get the printing policy for producing names for debug info.
836835
PrintingPolicy getPrintingPolicy() const;
837836

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)