[llvm] r275640 - [llvm-cov] Optionally use a symbol demangler when preparing reports

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 17 23:35:58 PDT 2016


Fixed with r275758:

  http://lab.llvm.org:8011/builders/clang-x86-win2008-selfhost/builds/9146

If you have access to that machine, I'd be curious to see what actually
gets passed to FileCheck in that test. This isn't urgent at all - ultimately
it turned out to be a minor formatting issue.

vedant

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



More information about the llvm-commits mailing list