Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
Expand Down Expand Up @@ -6277,6 +6278,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
pushDestroy(QualType::DK_nontrivial_c_struct, Ret.getAggregateAddress(),
RetTy);

// Generate function declaration DISuprogram in order to be used
// in debug info about call sites.
if (CGDebugInfo *DI = getDebugInfo()) {
// Ensure call site info would actually be emitted before collecting
// further callee info.
if (CalleeDecl && !CalleeDecl->hasAttr<NoDebugAttr>() &&
DI->getCallSiteRelatedAttrs() != llvm::DINode::FlagZero) {
CodeGenFunction CalleeCGF(CGM);
const GlobalDecl &CalleeGlobalDecl =
Callee.getAbstractInfo().getCalleeDecl();
CalleeCGF.CurGD = CalleeGlobalDecl;
FunctionArgList Args;
QualType ResTy = CalleeCGF.BuildFunctionArgList(CalleeGlobalDecl, Args);
DI->EmitFuncDeclForCallSite(
CI, DI->getFunctionType(CalleeDecl, ResTy, Args), CalleeGlobalDecl);
}
}

return Ret;
}

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4952,7 +4952,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,

void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
QualType CalleeType,
const FunctionDecl *CalleeDecl) {
GlobalDecl CalleeGlobalDecl) {
if (!CallOrInvoke)
return;
auto *Func = dyn_cast<llvm::Function>(CallOrInvoke->getCalledOperand());
Expand All @@ -4961,6 +4961,9 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
if (Func->getSubprogram())
return;

const FunctionDecl *CalleeDecl =
cast<FunctionDecl>(CalleeGlobalDecl.getDecl());

// Do not emit a declaration subprogram for a function with nodebug
// attribute, or if call site info isn't required.
if (CalleeDecl->hasAttr<NoDebugAttr>() ||
Expand All @@ -4971,7 +4974,8 @@ void CGDebugInfo::EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
// create the one describing the function in order to have complete
// call site debug info.
if (!CalleeDecl->isStatic() && !CalleeDecl->isInlined())
EmitFunctionDecl(CalleeDecl, CalleeDecl->getLocation(), CalleeType, Func);
EmitFunctionDecl(CalleeGlobalDecl, CalleeDecl->getLocation(), CalleeType,
Func);
}

void CGDebugInfo::EmitInlineFunctionStart(CGBuilderTy &Builder, GlobalDecl GD) {
Expand Down
11 changes: 5 additions & 6 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ class CGDebugInfo {
/// This is needed for call site debug info.
void EmitFuncDeclForCallSite(llvm::CallBase *CallOrInvoke,
QualType CalleeType,
const FunctionDecl *CalleeDecl);
GlobalDecl CalleeGlobalDecl);

/// Constructs the debug code for exiting a function.
void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn);
Expand Down Expand Up @@ -678,6 +678,10 @@ class CGDebugInfo {
/// Emit symbol for debugger that holds the pointer to the vtable.
void emitVTableSymbol(llvm::GlobalVariable *VTable, const CXXRecordDecl *RD);

/// Return flags which enable debug info emission for call sites, provided
/// that it is supported and enabled.
llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;

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
Expand Down Expand Up @@ -827,11 +831,6 @@ class CGDebugInfo {
unsigned LineNo, StringRef LinkageName,
llvm::GlobalVariable *Var, llvm::DIScope *DContext);


/// Return flags which enable debug info emission for call sites, provided
/// that it is supported and enabled.
llvm::DINode::DIFlags getCallSiteRelatedAttrs() const;

/// Get the printing policy for producing names for debug info.
PrintingPolicy getPrintingPolicy() const;

Expand Down
9 changes: 0 additions & 9 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6632,15 +6632,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
E == MustTailCall, E->getExprLoc());

if (auto *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
// Generate function declaration DISuprogram in order to be used
// in debug info about call sites.
if (CGDebugInfo *DI = getDebugInfo()) {
FunctionArgList Args;
QualType ResTy = BuildFunctionArgList(CalleeDecl, Args);
DI->EmitFuncDeclForCallSite(LocalCallOrInvoke,
DI->getFunctionType(CalleeDecl, ResTy, Args),
CalleeDecl);
}
if (CalleeDecl->hasAttr<RestrictAttr>() ||
CalleeDecl->hasAttr<AllocSizeAttr>()) {
// Function has 'malloc' (aka. 'restrict') or 'alloc_size' attribute.
Expand Down
25 changes: 25 additions & 0 deletions clang/test/DebugInfo/CXX/decl-member-call.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -O1 -triple x86_64-unknown_unknown -emit-llvm \
// RUN: -debug-info-kind=standalone -dwarf-version=5 %s -o - | FileCheck %s

// Ensure both nonmember and member calls to declared function
// have attached `DISubprogram`s.

int nonmember(int n);

struct S {
int x;
int member(int n);
};

int main(int argc, char** argv) {
struct S s = {};
int a = s.member(argc);
int b = nonmember(argc);
return a + b;
}

// CHECK: declare !dbg ![[SP1:[0-9]+]] noundef i32 @_ZN1S6memberEi(
// CHECK: declare !dbg ![[SP2:[0-9]+]] noundef i32 @_Z9nonmemberi(

// CHECK: ![[SP1]] = !DISubprogram(name: "member", linkageName: "_ZN1S6memberEi"
// CHECK: ![[SP2]] = !DISubprogram(name: "nonmember", linkageName: "_Z9nonmemberi"