<div dir="ltr">This test doesn't pass on Windows:<div><a href="http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/9141/steps/ninja%20check%201/logs/FAIL%3A%20LLVM%3A%3Ademangle.test">http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/9141/steps/ninja%20check%201/logs/FAIL%3A%20LLVM%3A%3Ademangle.test</a></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 15, 2016 at 3:44 PM, Vedant Kumar via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: vedantk<br>
Date: Fri Jul 15 17:44:57 2016<br>
New Revision: 275640<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=275640&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=275640&view=rev</a><br>
Log:<br>
[llvm-cov] Optionally use a symbol demangler when preparing reports<br>
<br>
Add an option to specify a symbol demangler (as well as options to the<br>
demangler). This can be used to make reports more human-readable.<br>
<br>
This option is especially useful in -output-dir mode, since it isn't as<br>
easy to manually pipe reports into a demangler in this mode.<br>
<br>
Added:<br>
llvm/trunk/test/tools/llvm-cov/demangle.test<br>
Modified:<br>
llvm/trunk/docs/CommandGuide/llvm-cov.rst<br>
llvm/trunk/tools/llvm-cov/CodeCoverage.cpp<br>
llvm/trunk/tools/llvm-cov/CoverageViewOptions.h<br>
<br>
Modified: llvm/trunk/docs/CommandGuide/llvm-cov.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-cov.rst?rev=275640&r1=275639&r2=275640&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-cov.rst?rev=275640&r1=275639&r2=275640&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/docs/CommandGuide/llvm-cov.rst (original)<br>
+++ llvm/trunk/docs/CommandGuide/llvm-cov.rst Fri Jul 15 17:44:57 2016<br>
@@ -248,6 +248,14 @@ OPTIONS<br>
PATH/functions.EXTENSION. When used in file view mode, a report for each file<br>
is written to PATH/REL_PATH_TO_FILE.EXTENSION.<br>
<br>
+.. option:: -Xdemangler=<TOOL>|<TOOL-OPTION><br>
+<br>
+ Specify a symbol demangler. This can be used to make reports more<br>
+ human-readable. This option can be specified multiple times to supply<br>
+ arguments to the demangler (e.g `-Xdemangler c++filt -Xdemangler -n` for C++).<br>
+ The demangler is expected to read a newline-separated list of symbols from<br>
+ stdin and write a newline-separated list of the same length to stdout.<br>
+<br>
.. option:: -line-coverage-gt=<N><br>
<br>
Show code coverage only for functions with line coverage greater than the<br>
<br>
Added: llvm/trunk/test/tools/llvm-cov/demangle.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/demangle.test?rev=275640&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/demangle.test?rev=275640&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-cov/demangle.test (added)<br>
+++ llvm/trunk/test/tools/llvm-cov/demangle.test Fri Jul 15 17:44:57 2016<br>
@@ -0,0 +1,4 @@<br>
+// RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -Xdemangler sed -Xdemangler 's/_/X/g' -filename-equivalence %S/showTemplateInstantiations.cpp | FileCheck %s<br>
+<br>
+// CHECK: XZ4funcIbEiTX:<br>
+// CHECK: XZ4funcIiEiTX:<br>
<br>
Modified: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=275640&r1=275639&r2=275640&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=275640&r1=275639&r2=275640&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp (original)<br>
+++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp Fri Jul 15 17:44:57 2016<br>
@@ -26,9 +26,12 @@<br>
#include "llvm/Support/CommandLine.h"<br>
#include "llvm/Support/FileSystem.h"<br>
#include "llvm/Support/Format.h"<br>
+#include "llvm/Support/MemoryBuffer.h"<br>
#include "llvm/Support/Path.h"<br>
#include "llvm/Support/Process.h"<br>
+#include "llvm/Support/Program.h"<br>
#include "llvm/Support/ThreadPool.h"<br>
+#include "llvm/Support/ToolOutputFile.h"<br>
#include <functional><br>
#include <system_error><br>
<br>
@@ -81,6 +84,12 @@ public:<br>
/// \brief Load the coverage mapping data. Return nullptr if an error occured.<br>
std::unique_ptr<CoverageMapping> load();<br>
<br>
+ /// \brief If a demangler is available, demangle all symbol names.<br>
+ void demangleSymbols(const CoverageMapping &Coverage);<br>
+<br>
+ /// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym.<br>
+ StringRef getSymbolForHumans(StringRef Sym) const;<br>
+<br>
int run(Command Cmd, int argc, const char **argv);<br>
<br>
typedef llvm::function_ref<int(int, const char **)> CommandLineParserType;<br>
@@ -101,6 +110,9 @@ public:<br>
std::string CoverageArch;<br>
<br>
private:<br>
+ /// A cache for demangled symbol names.<br>
+ StringMap<std::string> DemangledNames;<br>
+<br>
/// File paths (absolute, or otherwise) to input source files.<br>
std::vector<std::string> CollectedPaths;<br>
<br>
@@ -205,8 +217,9 @@ CodeCoverageTool::createFunctionView(con<br>
return nullptr;<br>
<br>
auto Expansions = FunctionCoverage.getExpansions();<br>
- auto View = SourceCoverageView::create(Function.Name, SourceBuffer.get(),<br>
- ViewOpts, std::move(FunctionCoverage));<br>
+ auto View = SourceCoverageView::create(getSymbolForHumans(Function.Name),<br>
+ SourceBuffer.get(), ViewOpts,<br>
+ std::move(FunctionCoverage));<br>
attachExpansionSubViews(*View, Expansions, Coverage);<br>
<br>
return View;<br>
@@ -230,9 +243,9 @@ CodeCoverageTool::createSourceFileView(S<br>
for (const auto *Function : Coverage.getInstantiations(SourceFile)) {<br>
auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);<br>
auto SubViewExpansions = SubViewCoverage.getExpansions();<br>
- auto SubView =<br>
- SourceCoverageView::create(Function->Name, SourceBuffer.get(), ViewOpts,<br>
- std::move(SubViewCoverage));<br>
+ auto SubView = SourceCoverageView::create(<br>
+ getSymbolForHumans(Function->Name), SourceBuffer.get(), ViewOpts,<br>
+ std::move(SubViewCoverage));<br>
attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);<br>
<br>
if (SubView) {<br>
@@ -289,9 +302,91 @@ std::unique_ptr<CoverageMapping> CodeCov<br>
}<br>
}<br>
<br>
+ demangleSymbols(*Coverage);<br>
+<br>
return Coverage;<br>
}<br>
<br>
+void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {<br>
+ if (!ViewOpts.hasDemangler())<br>
+ return;<br>
+<br>
+ // Pass function names to the demangler in a temporary file.<br>
+ int InputFD;<br>
+ SmallString<256> InputPath;<br>
+ std::error_code EC =<br>
+ sys::fs::createTemporaryFile("demangle-in", "list", InputFD, InputPath);<br>
+ if (EC) {<br>
+ error(InputPath, EC.message());<br>
+ return;<br>
+ }<br>
+ tool_output_file InputTOF{InputPath, InputFD};<br>
+<br>
+ unsigned NumSymbols = 0;<br>
+ for (const auto &Function : Coverage.getCoveredFunctions()) {<br>
+ InputTOF.os() << Function.Name << '\n';<br>
+ ++NumSymbols;<br>
+ }<br>
+ InputTOF.os().flush();<br>
+<br>
+ // Use another temporary file to store the demangler's output.<br>
+ int OutputFD;<br>
+ SmallString<256> OutputPath;<br>
+ EC = sys::fs::createTemporaryFile("demangle-out", "list", OutputFD,<br>
+ OutputPath);<br>
+ if (EC) {<br>
+ error(OutputPath, EC.message());<br>
+ return;<br>
+ }<br>
+ tool_output_file OutputTOF{OutputPath, OutputFD};<br>
+<br>
+ // Invoke the demangler.<br>
+ std::vector<const char *> ArgsV;<br>
+ for (const std::string &Arg : ViewOpts.DemanglerOpts)<br>
+ ArgsV.push_back(Arg.c_str());<br>
+ ArgsV.push_back(nullptr);<br>
+ StringRef InputPathRef{InputPath}, OutputPathRef{OutputPath}, StderrRef;<br>
+ const StringRef *Redirects[] = {&InputPathRef, &OutputPathRef, &StderrRef};<br>
+ std::string ErrMsg;<br>
+ int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(),<br>
+ /*env=*/nullptr, Redirects, /*secondsToWait=*/0,<br>
+ /*memoryLimit=*/0, &ErrMsg);<br>
+ if (RC) {<br>
+ error(ErrMsg, ViewOpts.DemanglerOpts[0]);<br>
+ return;<br>
+ }<br>
+<br>
+ // Parse the demangler's output.<br>
+ auto BufOrError = MemoryBuffer::getFile(OutputPath);<br>
+ if (!BufOrError) {<br>
+ error(OutputPath, BufOrError.getError().message());<br>
+ return;<br>
+ }<br>
+<br>
+ std::unique_ptr<MemoryBuffer> DemanglerBuf = std::move(*BufOrError);<br>
+<br>
+ SmallVector<StringRef, 8> Symbols;<br>
+ StringRef DemanglerData = DemanglerBuf->getBuffer();<br>
+ DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols,<br>
+ /*KeepEmpty=*/false);<br>
+ if (Symbols.size() != NumSymbols) {<br>
+ error("Demangler did not provide expected number of symbols");<br>
+ return;<br>
+ }<br>
+<br>
+ // Cache the demangled names.<br>
+ unsigned I = 0;<br>
+ for (const auto &Function : Coverage.getCoveredFunctions())<br>
+ DemangledNames[Function.Name] = Symbols[I++];<br>
+}<br>
+<br>
+StringRef CodeCoverageTool::getSymbolForHumans(StringRef Sym) const {<br>
+ const auto DemangledName = DemangledNames.find(Sym);<br>
+ if (DemangledName == DemangledNames.end())<br>
+ return Sym;<br>
+ return DemangledName->getValue();<br>
+}<br>
+<br>
int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {<br>
cl::opt<std::string, true> ObjectFilename(<br>
cl::Positional, cl::Required, cl::location(this->ObjectFilename),<br>
@@ -366,6 +461,9 @@ int CodeCoverageTool::run(Command Cmd, i<br>
"use-color", cl::desc("Emit colored output (default=autodetect)"),<br>
cl::init(cl::BOU_UNSET));<br>
<br>
+ cl::list<std::string> DemanglerOpts(<br>
+ "Xdemangler", cl::desc("<demangler-path>|<demangler-option>"));<br>
+<br>
auto commandLineParser = [&, this](int argc, const char **argv) -> int {<br>
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");<br>
ViewOpts.Debug = DebugDump;<br>
@@ -385,6 +483,18 @@ int CodeCoverageTool::run(Command Cmd, i<br>
break;<br>
}<br>
<br>
+ // If a demangler is supplied, check if it exists and register it.<br>
+ if (DemanglerOpts.size()) {<br>
+ auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]);<br>
+ if (!DemanglerPathOrErr) {<br>
+ error("Could not find the demangler!",<br>
+ DemanglerPathOrErr.getError().message());<br>
+ return 1;<br>
+ }<br>
+ DemanglerOpts[0] = *DemanglerPathOrErr;<br>
+ ViewOpts.DemanglerOpts.swap(DemanglerOpts);<br>
+ }<br>
+<br>
// Create the function filters<br>
if (!NameFilters.empty() || !NameRegexFilters.empty()) {<br>
auto NameFilterer = new CoverageFilters;<br>
<br>
Modified: llvm/trunk/tools/llvm-cov/CoverageViewOptions.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageViewOptions.h?rev=275640&r1=275639&r2=275640&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageViewOptions.h?rev=275640&r1=275639&r2=275640&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-cov/CoverageViewOptions.h (original)<br>
+++ llvm/trunk/tools/llvm-cov/CoverageViewOptions.h Fri Jul 15 17:44:57 2016<br>
@@ -11,6 +11,7 @@<br>
#define LLVM_COV_COVERAGEVIEWOPTIONS_H<br>
<br>
#include "RenderingSupport.h"<br>
+#include <vector><br>
<br>
namespace llvm {<br>
<br>
@@ -32,6 +33,7 @@ struct CoverageViewOptions {<br>
bool ShowFullFilenames;<br>
OutputFormat Format;<br>
std::string ShowOutputDirectory;<br>
+ std::vector<std::string> DemanglerOpts;<br>
<br>
/// \brief Change the output's stream color if the colors are enabled.<br>
ColoredRawOstream colored_ostream(raw_ostream &OS,<br>
@@ -41,6 +43,9 @@ struct CoverageViewOptions {<br>
<br>
/// \brief Check if an output directory has been specified.<br>
bool hasOutputDirectory() const { return !ShowOutputDirectory.empty(); }<br>
+<br>
+ /// \brief Check if a demangler has been specified.<br>
+ bool hasDemangler() const { return !DemanglerOpts.empty(); }<br>
};<br>
}<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>