yonghong-song updated this revision to Diff 337993. yonghong-song added a comment.
- check Fn->getSubprogram() before emit debuginfo. This is consistent with EmitFuncDeclForCallSite() and is better than checking FD->isDefined() as we may hit multiple DeclRefExpr and all of them will go through emitting debuginfo. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D100567/new/ https://reviews.llvm.org/D100567 Files: clang/include/clang/Basic/TargetInfo.h clang/lib/Basic/Targets/BPF.h clang/lib/CodeGen/CGExpr.cpp clang/lib/Sema/SemaDecl.cpp clang/test/CodeGen/debug-info-extern-callback.c Index: clang/test/CodeGen/debug-info-extern-callback.c =================================================================== --- /dev/null +++ clang/test/CodeGen/debug-info-extern-callback.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -x c -debug-info-kind=limited -triple bpf-linux-gnu -emit-llvm %s -o - | FileCheck %s + +extern int do_work(int); +long bpf_helper(void *callback_fn); +long prog() { + return bpf_helper(&do_work); +} + +// CHECK: declare !dbg ![[FUNC:[0-9]+]] i32 @do_work(i32) +// CHECK: ![[FUNC]] = !DISubprogram(name: "do_work" Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -12667,7 +12667,7 @@ Diag(Var->getLocation(), diag::note_private_extern); } - if (Context.getTargetInfo().allowDebugInfoForExternalVar() && + if (Context.getTargetInfo().allowDebugInfoForExternalRef() && !Var->isInvalidDecl() && !getLangOpts().CPlusPlus) ExternalDeclarations.push_back(Var); Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -2834,8 +2834,20 @@ return LV; } - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) - return EmitFunctionDeclLValue(*this, E, FD); + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + LValue LV = EmitFunctionDeclLValue(*this, E, FD); + + // Emit debuginfo for the function declaration if the target wants to. + if (getContext().getTargetInfo().allowDebugInfoForExternalRef()) { + auto *Fn = dyn_cast<llvm::Function>(LV.getPointer(*this)); + if (!Fn->getSubprogram()) { + CGM.getModuleDebugInfo()->EmitFunctionDecl(FD, FD->getLocation(), + T, Fn); + } + } + + return LV; + } // FIXME: While we're emitting a binding from an enclosing scope, all other // DeclRefExprs we see should be implicitly treated as if they also refer to Index: clang/lib/Basic/Targets/BPF.h =================================================================== --- clang/lib/Basic/Targets/BPF.h +++ clang/lib/Basic/Targets/BPF.h @@ -76,7 +76,7 @@ return None; } - bool allowDebugInfoForExternalVar() const override { return true; } + bool allowDebugInfoForExternalRef() const override { return true; } CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { switch (CC) { Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -1538,8 +1538,8 @@ virtual void setAuxTarget(const TargetInfo *Aux) {} - /// Whether target allows debuginfo types for decl only variables. - virtual bool allowDebugInfoForExternalVar() const { return false; } + /// Whether target allows debuginfo types for decl only variables/functions. + virtual bool allowDebugInfoForExternalRef() const { return false; } protected: /// Copy type and layout related info.
Index: clang/test/CodeGen/debug-info-extern-callback.c =================================================================== --- /dev/null +++ clang/test/CodeGen/debug-info-extern-callback.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -x c -debug-info-kind=limited -triple bpf-linux-gnu -emit-llvm %s -o - | FileCheck %s + +extern int do_work(int); +long bpf_helper(void *callback_fn); +long prog() { + return bpf_helper(&do_work); +} + +// CHECK: declare !dbg ![[FUNC:[0-9]+]] i32 @do_work(i32) +// CHECK: ![[FUNC]] = !DISubprogram(name: "do_work" Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -12667,7 +12667,7 @@ Diag(Var->getLocation(), diag::note_private_extern); } - if (Context.getTargetInfo().allowDebugInfoForExternalVar() && + if (Context.getTargetInfo().allowDebugInfoForExternalRef() && !Var->isInvalidDecl() && !getLangOpts().CPlusPlus) ExternalDeclarations.push_back(Var); Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -2834,8 +2834,20 @@ return LV; } - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) - return EmitFunctionDeclLValue(*this, E, FD); + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + LValue LV = EmitFunctionDeclLValue(*this, E, FD); + + // Emit debuginfo for the function declaration if the target wants to. + if (getContext().getTargetInfo().allowDebugInfoForExternalRef()) { + auto *Fn = dyn_cast<llvm::Function>(LV.getPointer(*this)); + if (!Fn->getSubprogram()) { + CGM.getModuleDebugInfo()->EmitFunctionDecl(FD, FD->getLocation(), + T, Fn); + } + } + + return LV; + } // FIXME: While we're emitting a binding from an enclosing scope, all other // DeclRefExprs we see should be implicitly treated as if they also refer to Index: clang/lib/Basic/Targets/BPF.h =================================================================== --- clang/lib/Basic/Targets/BPF.h +++ clang/lib/Basic/Targets/BPF.h @@ -76,7 +76,7 @@ return None; } - bool allowDebugInfoForExternalVar() const override { return true; } + bool allowDebugInfoForExternalRef() const override { return true; } CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { switch (CC) { Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -1538,8 +1538,8 @@ virtual void setAuxTarget(const TargetInfo *Aux) {} - /// Whether target allows debuginfo types for decl only variables. - virtual bool allowDebugInfoForExternalVar() const { return false; } + /// Whether target allows debuginfo types for decl only variables/functions. + virtual bool allowDebugInfoForExternalRef() const { return false; } protected: /// Copy type and layout related info.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits