<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>