From: Scott Linder Date: Mon, 26 Feb 2018 17:32:31 +0000 (+0000) Subject: [DebugInfo] Support DWARF v5 source code embedding extension X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7fab66ed2f7638c119451e5e91adac8afb273277;p=clang [DebugInfo] Support DWARF v5 source code embedding extension In DWARF v5 the Line Number Program Header is extensible, allowing values with new content types. This vendor extension to DWARF v5 allows source text to be embedded directly in the line tables of the debug line section. Add new flag (-g[no-]embed-source) to Driver and CC1 which indicates that source should be passed through to LLVM during CodeGen. Differential Revision: https://reviews.llvm.org/D42766 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@326102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/ClangCommandLineReference.rst b/docs/ClangCommandLineReference.rst index fa429040be..595909eef0 100644 --- a/docs/ClangCommandLineReference.rst +++ b/docs/ClangCommandLineReference.rst @@ -2573,6 +2573,10 @@ Debug information flags .. option:: -gdwarf-aranges +.. option:: -gembed-source + +.. option:: -gno-embed-source + .. option:: -ggnu-pubnames .. option:: -grecord-gcc-switches, -gno-record-gcc-switches diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 21d42a54f8..04ed098e89 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1703,6 +1703,11 @@ def gz : Flag<["-"], "gz">, Group, HelpText<"DWARF debug sections compression type">; def gz_EQ : Joined<["-"], "gz=">, Group, HelpText<"DWARF debug sections compression type">; +def gembed_source : Flag<["-"], "gembed-source">, Group, Flags<[CC1Option]>, + HelpText<"Embed source text in DWARF debug sections">; +def gno_embed_source : Flag<["-"], "gno-embed-source">, Group, + Flags<[DriverOption]>, + HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>, HelpText<"Display available options">; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 0e4c4617b2..50addf7ff3 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -318,6 +318,9 @@ CODEGENOPT(GnuPubnames, 1, 0) CODEGENOPT(NoPLT, 1, 0) +/// Whether to embed source in DWARF debug line section. +CODEGENOPT(EmbedSource, 1, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 3dab8c3884..403957214a 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -385,6 +385,19 @@ CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const { return llvm::DIFile::CSK_MD5; } +Optional CGDebugInfo::getSource(const SourceManager &SM, FileID FID) { + if (!CGM.getCodeGenOpts().EmbedSource) + return None; + + bool SourceInvalid = false; + StringRef Source = SM.getBufferData(FID, &SourceInvalid); + + if (SourceInvalid) + return None; + + return Source; +} + llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. @@ -416,16 +429,19 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()), remapDIPath(getCurrentDirname()), - CSInfo); + CSInfo, + getSource(SM, SM.getFileID(Loc))); DIFileCache[fname].reset(F); return F; } llvm::DIFile *CGDebugInfo::getOrCreateMainFile() { - return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory()), - TheCU->getFile()->getChecksum()); + return DBuilder.createFile( + remapDIPath(TheCU->getFilename()), + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksum(), + CGM.getCodeGenOpts().EmbedSource ? TheCU->getSource() : None); } std::string CGDebugInfo::remapDIPath(StringRef Path) const { @@ -558,7 +574,9 @@ void CGDebugInfo::CreateCompileUnit() { TheCU = DBuilder.createCompileUnit( LangTag, DBuilder.createFile(remapDIPath(MainFileName), - remapDIPath(getCurrentDirname()), CSInfo), + remapDIPath(getCurrentDirname()), + CSInfo, + getSource(SM, SM.getMainFileID())), Producer, LO.Optimize || CGOpts.PrepareForLTO || CGOpts.EmitSummaryIndex, CGOpts.DwarfDebugFlags, RuntimeVers, CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind, @@ -2108,6 +2126,7 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod, : ~1ULL; llvm::DIBuilder DIB(CGM.getModule()); DIB.createCompileUnit(TheCU->getSourceLanguage(), + // TODO: Support "Source" from external AST providers? DIB.createFile(Mod.getModuleName(), Mod.getPath()), TheCU->getProducer(), true, StringRef(), 0, Mod.getASTFile(), llvm::DICompileUnit::FullDebug, diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index a8b0c613cc..459d7e00b6 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -502,6 +502,9 @@ private: Optional computeChecksum(FileID FID, SmallString<32> &Checksum) const; + /// Get the source of the given file ID. + Optional getSource(const SourceManager &SM, FileID FID); + /// Get the file debug info descriptor for the input location. llvm::DIFile *getOrCreateFile(SourceLocation Loc); diff --git a/lib/Driver/ToolChains/AMDGPU.h b/lib/Driver/ToolChains/AMDGPU.h index 36114d0dab..588c24032b 100644 --- a/lib/Driver/ToolChains/AMDGPU.h +++ b/lib/Driver/ToolChains/AMDGPU.h @@ -56,7 +56,7 @@ protected: public: AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - unsigned GetDefaultDwarfVersion() const override { return 2; } + unsigned GetDefaultDwarfVersion() const override { return 5; } bool IsIntegratedAssemblerDefault() const override { return true; } llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index a19c5031ce..a2248ddaa9 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3024,6 +3024,18 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug) DebugInfoKind = codegenoptions::FullDebugInfo; + if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source, false)) { + // Source embedding is a vendor extension to DWARF v5. By now we have + // checked if a DWARF version was stated explicitly, and have otherwise + // fallen back to the target default, so if this is still not at least 5 we + // emit an error. + if (DWARFVersion < 5) + D.Diag(diag::err_drv_argument_only_allowed_with) + << Args.getLastArg(options::OPT_gembed_source)->getAsString(Args) + << "-gdwarf-5"; + CmdArgs.push_back("-gembed-source"); + } + RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion, DebuggerTuning); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 443c550bcb..4be390b49b 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -545,6 +545,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); + Opts.EmbedSource = Args.hasArg(OPT_gembed_source); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); diff --git a/test/CodeGen/Inputs/debug-info-embed-source.c b/test/CodeGen/Inputs/debug-info-embed-source.c new file mode 100644 index 0000000000..2fb55eed6b --- /dev/null +++ b/test/CodeGen/Inputs/debug-info-embed-source.c @@ -0,0 +1 @@ +void foo() { } diff --git a/test/CodeGen/debug-info-embed-source.c b/test/CodeGen/debug-info-embed-source.c new file mode 100644 index 0000000000..3b607b61f7 --- /dev/null +++ b/test/CodeGen/debug-info-embed-source.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm %p/Inputs/debug-info-embed-source.c -o - | FileCheck %s --check-prefix=NOEMBED +// RUN: %clang_cc1 -gembed-source -debug-info-kind=limited -emit-llvm %p/Inputs/debug-info-embed-source.c -o - | FileCheck %s --check-prefix=EMBED + +// NOEMBED-NOT: !DIFile({{.*}}source: +// EMBED: !DIFile({{.*}}source: "void foo() { }\0A" diff --git a/test/Driver/amdgpu-toolchain.c b/test/Driver/amdgpu-toolchain.c index 52a71975b7..bd6bf7e341 100644 --- a/test/Driver/amdgpu-toolchain.c +++ b/test/Driver/amdgpu-toolchain.c @@ -3,4 +3,4 @@ // AS_LINK: ld.lld{{.*}} "-shared" // RUN: %clang -### -g -target amdgcn--amdhsa -mcpu=kaveri %s 2>&1 | FileCheck -check-prefix=DWARF_VER %s -// DWARF_VER: "-dwarf-version=2" +// DWARF_VER: "-dwarf-version=5" diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c index 3bec1e141d..b3f7aa60e3 100644 --- a/test/Driver/debug-options.c +++ b/test/Driver/debug-options.c @@ -245,3 +245,13 @@ // RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=NOMACRO %s // MACRO: "-debug-info-macro" // NOMACRO-NOT: "-debug-info-macro" +// +// RUN: %clang -### -gdwarf-5 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_5 %s +// RUN: %clang -### -gdwarf-2 -gembed-source %s 2>&1 | FileCheck -check-prefix=GEMBED_2 %s +// RUN: %clang -### -gdwarf-5 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_5 %s +// RUN: %clang -### -gdwarf-2 -gno-embed-source %s 2>&1 | FileCheck -check-prefix=NOGEMBED_2 %s +// +// GEMBED_5: "-gembed-source" +// GEMBED_2: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5' +// NOGEMBED_5-NOT: "-gembed-source" +// NOGEMBED_2-NOT: error: invalid argument '-gembed-source' only allowed with '-gdwarf-5'