diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 6504ab41d269a..15d3ed8d8bc5c 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -296,6 +296,10 @@ class IRGenOptions { /// indexing info. PathRemapper FilePrefixMap; + /// Indicates whether or not the frontend should generate callsite information + /// in the debug info. + bool DebugCallsiteInfo = false; + /// What level of debug info to generate. IRGenDebugInfoLevel DebugInfoLevel : 2; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index a4e622a58acc2..b2e1d84293ea5 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -2191,6 +2191,10 @@ def cas_backend: Flag<["-"], "cas-backend">, Flags<[FrontendOption, NoDriverOption]>, HelpText<"Enable using CASBackend for object file output">; +def debug_callsite_info: Flag<["-"], "debug-callsite-info">, + Flags<[FrontendOption, NoDriverOption]>, + HelpText<"Generate callsite information in debug info">; + def cas_backend_mode: Joined<["-"], "cas-backend-mode=">, Flags<[FrontendOption, NoDriverOption]>, HelpText<"CASBackendMode for output kind">, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index bc6904d104a52..7aaba95de2709 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -3681,6 +3681,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Opts.UseCASBackend |= Args.hasArg(OPT_cas_backend); Opts.EmitCASIDFile |= Args.hasArg(OPT_cas_emit_casid_file); + Opts.DebugCallsiteInfo |= Args.hasArg(OPT_debug_callsite_info); + return false; } diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 5e71b17010c91..4a5cd3f813e1e 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -284,6 +284,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { void emitPackCountParameter(IRGenFunction &IGF, llvm::Value *Metadata, SILDebugVariable VarInfo); + /// Return flags which enable debug info emission for call sites, provided + /// that it is supported and enabled. + llvm::DINode::DIFlags getCallSiteRelatedAttrs() const; + /// Return the DIBuilder. llvm::DIBuilder &getBuilder() { return DBuilder; } @@ -3042,6 +3046,33 @@ void IRGenDebugInfoImpl::emitImport(ImportDecl *D) { ImportedModules.insert(Imported.importedModule); } +/// This is effectively \p clang::CGDebugInfo::getCallSiteRelatedAttrs(). +llvm::DINode::DIFlags IRGenDebugInfoImpl::getCallSiteRelatedAttrs() const { + + // Do not generate callsite attributes if unless the -gen-callsite-info flag + // is passed. + if (!Opts.DebugCallsiteInfo) + return llvm::DINode::FlagZero; + + auto SwiftLangOpts = IGM.Context.LangOpts; + auto Loader = IGM.getSILModule().getASTContext().getClangModuleLoader(); + auto *Importer = static_cast(&*Loader); + auto &CGO = Importer->getCodeGenOpts(); + + // Do not generate callsite attributes if there is no debug info to be + // emitted. + if (CGO.getDebugInfo() == llvm::codegenoptions::NoDebugInfo || + CGO.getDebugInfo() == llvm::codegenoptions::LocTrackingOnly) + return llvm::DINode::FlagZero; + + // Callsite attributes are available in DWARFv5. However, for swift, lldb can + // accept these attributes as if they were part of DWARFv4. + if (Opts.DWARFVersion < 4) + return llvm::DINode::FlagZero; + + return llvm::DINode::FlagAllCallsDescribed; +} + llvm::DISubprogram *IRGenDebugInfoImpl::emitFunction(SILFunction &SILFn, llvm::Function *Fn) { auto *DS = SILFn.getDebugScope(); @@ -3193,9 +3224,10 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn, } // Construct the DISubprogram. - llvm::DISubprogram *SP = DBuilder.createFunction( - Scope, Name, LinkageName, File, Line, DIFnTy, ScopeLine, Flags, SPFlags, - TemplateParameters, Decl, Error); + llvm::DISubprogram *SP = + DBuilder.createFunction(Scope, Name, LinkageName, File, Line, DIFnTy, + ScopeLine, Flags | getCallSiteRelatedAttrs(), + SPFlags, TemplateParameters, Decl, Error); if (Fn && !Fn->isDeclaration()) Fn->setSubprogram(SP); diff --git a/test/DebugInfo/call-site-info.swift b/test/DebugInfo/call-site-info.swift new file mode 100644 index 0000000000000..37150edf59b7b --- /dev/null +++ b/test/DebugInfo/call-site-info.swift @@ -0,0 +1,7 @@ +// RUN: %target-swift-frontend -debug-callsite-info -emit-ir -parse-as-library -g -O -module-name S %s -o - | %FileCheck %s +// CHECK: {{[0-9]+}} = distinct !DISubprogram(name: "f", linkageName: {{.*}}, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}, scopeLine: {{[0-9]+}}, flags: DIFlagAllCallsDescribed +// CHECK: {{[0-9]+}} = distinct !DISubprogram(linkageName: {{.*}}, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: {{.*}} DIFlagAllCallsDescribed + +public struct S { + public func f() {} +}