[llvm] r275640 - [llvm-cov] Optionally use a symbol demangler when preparing reports
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 15 15:44:57 PDT 2016
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(); }
};
}
More information about the llvm-commits
mailing list