Skip to content

Commit 0f65168

Browse files
committed
[clang] Add DISuprogram and DIE for a func decl
Attach a unique DISubprogram to a function declaration that will be used for call site debug info. ([7/13] Introduce the debug entry values.) Co-authored-by: Ananth Sowda <asowda@cisco.com> Co-authored-by: Nikola Prica <nikola.prica@rt-rk.com> Co-authored-by: Ivan Baev <ibaev@cisco.com> Differential Revision: https://reviews.llvm.org/D60714 llvm-svn: 364502
1 parent 852f45b commit 0f65168

File tree

5 files changed

+73
-6
lines changed

5 files changed

+73
-6
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,8 @@ class FunctionDecl : public DeclaratorDecl,
23962396

23972397
bool doesDeclarationForceExternallyVisibleDefinition() const;
23982398

2399+
bool isStatic() const { return getStorageClass() == SC_Static; }
2400+
23992401
/// Whether this function declaration represents an C++ overloaded
24002402
/// operator, e.g., "operator+".
24012403
bool isOverloadedOperator() const {

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3619,7 +3619,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
36193619
}
36203620

36213621
void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
3622-
QualType FnType) {
3622+
QualType FnType, llvm::Function *Fn) {
36233623
StringRef Name;
36243624
StringRef LinkageName;
36253625

@@ -3629,7 +3629,9 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
36293629

36303630
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
36313631
llvm::DIFile *Unit = getOrCreateFile(Loc);
3632-
llvm::DIScope *FDContext = getDeclContextDescriptor(D);
3632+
bool IsDeclForCallSite = Fn ? true : false;
3633+
llvm::DIScope *FDContext =
3634+
IsDeclForCallSite ? Unit : getDeclContextDescriptor(D);
36333635
llvm::DINodeArray TParamsArray;
36343636
if (isa<FunctionDecl>(D)) {
36353637
// If there is a DISubprogram for this function available then use it.
@@ -3656,10 +3658,38 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
36563658
if (CGM.getLangOpts().Optimize)
36573659
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
36583660

3659-
DBuilder.retainType(DBuilder.createFunction(
3661+
llvm::DISubprogram *SP = DBuilder.createFunction(
36603662
FDContext, Name, LinkageName, Unit, LineNo,
36613663
getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags,
3662-
TParamsArray.get(), getFunctionDeclaration(D)));
3664+
TParamsArray.get(), getFunctionDeclaration(D));
3665+
3666+
if (IsDeclForCallSite)
3667+
Fn->setSubprogram(SP);
3668+
3669+
DBuilder.retainType(SP);
3670+
}
3671+
3672+
void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
3673+
QualType CalleeType,
3674+
const FunctionDecl *CalleeDecl) {
3675+
auto &CGOpts = CGM.getCodeGenOpts();
3676+
if (!CGOpts.EnableDebugEntryValues || !CGM.getLangOpts().Optimize ||
3677+
!CallOrInvoke ||
3678+
CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo)
3679+
return;
3680+
3681+
auto *Func = CallOrInvoke->getCalledFunction();
3682+
if (!Func)
3683+
return;
3684+
3685+
// If there is no DISubprogram attached to the function being called,
3686+
// create the one describing the function in order to have complete
3687+
// call site debug info.
3688+
if (Func->getSubprogram())
3689+
return;
3690+
3691+
if (!CalleeDecl->isStatic() && !CalleeDecl->isInlined())
3692+
EmitFunctionDecl(CalleeDecl, CalleeDecl->getLocation(), CalleeType, Func);
36633693
}
36643694

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

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,15 @@ class CGDebugInfo {
409409
void EmitInlineFunctionEnd(CGBuilderTy &Builder);
410410

411411
/// Emit debug info for a function declaration.
412-
void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType);
412+
/// \p Fn is set only when a declaration for a debug call site gets created.
413+
void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
414+
QualType FnType, llvm::Function *Fn = nullptr);
415+
416+
/// Emit debug info for an extern function being called.
417+
/// This is needed for call site debug info.
418+
void EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
419+
QualType CalleeType,
420+
const FunctionDecl *CalleeDecl);
413421

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

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4856,7 +4856,19 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
48564856
Callee.setFunctionPointer(CalleePtr);
48574857
}
48584858

4859-
return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr, E->getExprLoc());
4859+
llvm::CallBase *CallOrInvoke = nullptr;
4860+
RValue Call = EmitCall(FnInfo, Callee, ReturnValue, Args, &CallOrInvoke,
4861+
E->getExprLoc());
4862+
4863+
// Generate function declaration DISuprogram in order to be used
4864+
// in debug info about call sites.
4865+
if (CGDebugInfo *DI = getDebugInfo()) {
4866+
if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl))
4867+
DI->EmitFuncDeclForCallSite(CallOrInvoke, QualType(FnType, 0),
4868+
CalleeDecl);
4869+
}
4870+
4871+
return Call;
48604872
}
48614873

48624874
LValue CodeGenFunction::
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang -Xclang -femit-debug-entry-values -g -O2 -target x86_64-none-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-EXT
2+
// CHECK-EXT: !DISubprogram(name: "fn1"
3+
4+
// RUN: %clang -g -O2 -target x86_64-none-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
5+
// CHECK-NOT: !DISubprogram(name: "fn1"
6+
7+
extern int fn1(int a, int b);
8+
9+
int fn2 () {
10+
int x = 4, y = 5;
11+
int res = fn1(x, y);
12+
13+
return res;
14+
}
15+

0 commit comments

Comments
 (0)