[llvm] r346506 - [llvm-cov] Add lcov tracefile export format.
Max Moroz via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 9 08:10:44 PST 2018
Author: dor1s
Date: Fri Nov 9 08:10:44 2018
New Revision: 346506
URL: http://llvm.org/viewvc/llvm-project?rev=346506&view=rev
Log:
[llvm-cov] Add lcov tracefile export format.
Summary:
lcov tracefiles are used by various coverage reporting tools and build
systems (e.g., Bazel). It is a simple text-based format to parse and
more convenient to use than the JSON export format, which needs
additional processing to map regions/segments back to line numbers.
It's a little unfortunate that "text" format is now overloaded to refer
specifically to JSON for export, but I wanted to avoid making any
breaking changes to the UI of the llvm-cov tool at this time.
Patch by Tony Allevato (@allevato).
Reviewers: Dor1s, vsk
Reviewed By: Dor1s, vsk
Subscribers: mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D54266
Added:
llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts-lcov.test
llvm/trunk/tools/llvm-cov/CoverageExporterLcov.cpp
llvm/trunk/tools/llvm-cov/CoverageExporterLcov.h
Modified:
llvm/trunk/docs/CommandGuide/llvm-cov.rst
llvm/trunk/docs/ReleaseNotes.rst
llvm/trunk/tools/llvm-cov/CMakeLists.txt
llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
llvm/trunk/tools/llvm-cov/CoverageViewOptions.h
llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
Modified: llvm/trunk/docs/CommandGuide/llvm-cov.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-cov.rst?rev=346506&r1=346505&r2=346506&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llvm-cov.rst (original)
+++ llvm/trunk/docs/CommandGuide/llvm-cov.rst Fri Nov 9 08:10:44 2018
@@ -374,9 +374,15 @@ SYNOPSIS
DESCRIPTION
^^^^^^^^^^^
-The :program:`llvm-cov export` command exports regions, functions, expansions,
-and summaries of the coverage of the binaries *BIN*,... using the profile data
-*PROFILE* as JSON. It can optionally be filtered to only export the coverage
+The :program:`llvm-cov export` command exports coverage data of the binaries
+*BIN*,... using the profile data *PROFILE* in either JSON or lcov trace file
+format.
+
+When exporting JSON, the regions, functions, expansions, and summaries of the
+coverage data will be exported. When exporting an lcov trace file, the
+line-based coverage and summaries will be exported.
+
+The exported data can optionally be filtered to only export the coverage
for the files listed in *SOURCES*.
For information on compiling programs for coverage and generating profile data,
@@ -392,12 +398,18 @@ OPTIONS
universal binary or to use an architecture that does not match a
non-universal binary.
+.. option:: -format=<FORMAT>
+
+ Use the specified output format. The supported formats are: "text" (JSON),
+ "lcov".
+
.. option:: -summary-only
Export only summary information for each file in the coverage data. This mode
will not export coverage information for smaller units such as individual
- functions or regions. The result will be the same as produced by :program:
- `llvm-cov report` command, but presented in JSON format rather than text.
+ functions or regions. The result will contain the same information as produced
+ by the :program:`llvm-cov report` command, but presented in JSON or lcov
+ format rather than text.
.. option:: -ignore-filename-regex=<PATTERN>
Modified: llvm/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ReleaseNotes.rst?rev=346506&r1=346505&r2=346506&view=diff
==============================================================================
--- llvm/trunk/docs/ReleaseNotes.rst (original)
+++ llvm/trunk/docs/ReleaseNotes.rst Fri Nov 9 08:10:44 2018
@@ -40,7 +40,8 @@ Non-comprehensive list of changes in thi
functionality, or simply have a lot to talk about), see the `NOTE` below
for adding a new subsection.
-* Note..
+* The **llvm-cov** tool can now export lcov trace files using the
+ `-format=lcov` option of the `export` command.
.. NOTE
If you would like to document a larger change, then you can add a
Added: llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts-lcov.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts-lcov.test?rev=346506&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts-lcov.test (added)
+++ llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts-lcov.test Fri Nov 9 08:10:44 2018
@@ -0,0 +1,38 @@
+// FULL: SF:{{.*}}showLineExecutionCounts.cpp
+// FULL: FN:6,main
+// FULL: FNDA:161,main
+// FULL: FNF:1
+// FULL: FNH:1
+int main() { // FULL: DA:[[@LINE]],161
+ int x = 0; // FULL: DA:[[@LINE]],161
+ // FULL: DA:[[@LINE]],161
+ if (x) { // FULL: DA:[[@LINE]],161
+ x = 0; // FULL: DA:[[@LINE]],0
+ } else { // FULL: DA:[[@LINE]],161
+ x = 1; // FULL: DA:[[@LINE]],161
+ } // FULL: DA:[[@LINE]],161
+ // FULL: DA:[[@LINE]],161
+ for (int i = 0; i < 100; ++i) { // FULL: DA:[[@LINE]],16261
+ x = 1; // FULL: DA:[[@LINE]],16100
+ } // FULL: DA:[[@LINE]],16100
+ // FULL: DA:[[@LINE]],161
+ x = x < 10 ? x + 1 : x - 1; // FULL: DA:[[@LINE]],161
+ x = x > 10 ? // FULL: DA:[[@LINE]],161
+ x - 1: // FULL: DA:[[@LINE]],0
+ x + 1; // FULL: DA:[[@LINE]],161
+ // FULL: DA:[[@LINE]],161
+ return 0; // FULL: DA:[[@LINE]],161
+} // FULL: DA:[[@LINE]],161
+// FULL: LF:20
+// FULL: LH:18
+// FULL: end_of_record
+// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
+// RUN: llvm-cov export -format=lcov %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata %s | FileCheck -check-prefixes=FULL %s
+
+// RUN: llvm-cov export -format=lcov -summary-only %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata %s | FileCheck -check-prefixes=SUMMARYONLY %s
+// SUMMARYONLY: SF:{{.*}}showLineExecutionCounts.cpp
+// SUMMARYONLY: FNF:1
+// SUMMARYONLY: FNH:1
+// SUMMARYONLY: LF:20
+// SUMMARYONLY: LH:18
+// SUMMARYONLY: end_of_record
Modified: llvm/trunk/tools/llvm-cov/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CMakeLists.txt?rev=346506&r1=346505&r2=346506&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-cov/CMakeLists.txt Fri Nov 9 08:10:44 2018
@@ -5,6 +5,7 @@ add_llvm_tool(llvm-cov
gcov.cpp
CodeCoverage.cpp
CoverageExporterJson.cpp
+ CoverageExporterLcov.cpp
CoverageFilters.cpp
CoverageReport.cpp
CoverageSummaryInfo.cpp
Modified: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=346506&r1=346505&r2=346506&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp Fri Nov 9 08:10:44 2018
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "CoverageExporterJson.h"
+#include "CoverageExporterLcov.h"
#include "CoverageFilters.h"
#include "CoverageReport.h"
#include "CoverageSummaryInfo.h"
@@ -566,7 +567,9 @@ int CodeCoverageTool::run(Command Cmd, i
cl::values(clEnumValN(CoverageViewOptions::OutputFormat::Text, "text",
"Text output"),
clEnumValN(CoverageViewOptions::OutputFormat::HTML, "html",
- "HTML output")),
+ "HTML output"),
+ clEnumValN(CoverageViewOptions::OutputFormat::Lcov, "lcov",
+ "lcov tracefile output")),
cl::init(CoverageViewOptions::OutputFormat::Text));
cl::opt<std::string> PathRemap(
@@ -674,6 +677,11 @@ int CodeCoverageTool::run(Command Cmd, i
errs() << "Color output cannot be disabled when generating html.\n";
ViewOpts.Colors = true;
break;
+ case CoverageViewOptions::OutputFormat::Lcov:
+ if (UseColor == cl::BOU_TRUE)
+ errs() << "Color output cannot be enabled when generating lcov.\n";
+ ViewOpts.Colors = false;
+ break;
}
// If path-equivalence was given and is a comma seperated pair then set
@@ -833,6 +841,11 @@ int CodeCoverageTool::doShow(int argc, c
if (Err)
return Err;
+ if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) {
+ error("Lcov format should be used with 'llvm-cov export'.");
+ return 1;
+ }
+
ViewOpts.ShowLineNumbers = true;
ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 ||
!ShowRegions || ShowBestLineRegionsCounts;
@@ -964,6 +977,9 @@ int CodeCoverageTool::doReport(int argc,
if (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML) {
error("HTML output for summary reports is not yet supported.");
return 1;
+ } else if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) {
+ error("Lcov format should be used with 'llvm-cov export'.");
+ return 1;
}
auto Coverage = load();
@@ -995,8 +1011,10 @@ int CodeCoverageTool::doExport(int argc,
if (Err)
return Err;
- if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text) {
- error("Coverage data can only be exported as textual JSON.");
+ if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text &&
+ ViewOpts.Format != CoverageViewOptions::OutputFormat::Lcov) {
+ error("Coverage data can only be exported as textual JSON or an "
+ "lcov tracefile.");
return 1;
}
@@ -1006,12 +1024,29 @@ int CodeCoverageTool::doExport(int argc,
return 1;
}
- auto Exporter = CoverageExporterJson(*Coverage.get(), ViewOpts, outs());
+ std::unique_ptr<CoverageExporter> Exporter;
+
+ switch (ViewOpts.Format) {
+ case CoverageViewOptions::OutputFormat::Text:
+ Exporter = llvm::make_unique<CoverageExporterJson>(*Coverage.get(),
+ ViewOpts, outs());
+ break;
+ case CoverageViewOptions::OutputFormat::HTML:
+ // Unreachable because we should have gracefully terminated with an error
+ // above.
+ llvm_unreachable("Export in HTML is not supported!");
+ case CoverageViewOptions::OutputFormat::Lcov:
+ Exporter = llvm::make_unique<CoverageExporterLcov>(*Coverage.get(),
+ ViewOpts, outs());
+ break;
+ default:
+ llvm_unreachable("Unknown coverage output format!");
+ }
if (SourceFiles.empty())
- Exporter.renderRoot(IgnoreFilenameFilters);
+ Exporter->renderRoot(IgnoreFilenameFilters);
else
- Exporter.renderRoot(SourceFiles);
+ Exporter->renderRoot(SourceFiles);
return 0;
}
Added: llvm/trunk/tools/llvm-cov/CoverageExporterLcov.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageExporterLcov.cpp?rev=346506&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageExporterLcov.cpp (added)
+++ llvm/trunk/tools/llvm-cov/CoverageExporterLcov.cpp Fri Nov 9 08:10:44 2018
@@ -0,0 +1,125 @@
+//===- CoverageExporterLcov.cpp - Code coverage export --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements export of code coverage data to lcov trace file format.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//
+// The trace file code coverage export follows the following format (see also
+// https://linux.die.net/man/1/geninfo). Each quoted string appears on its own
+// line; the indentation shown here is only for documentation purposes.
+//
+// - for each source file:
+// - "SF:<absolute path to source file>"
+// - for each function:
+// - "FN:<line number of function start>,<function name>"
+// - for each function:
+// - "FNDA:<execution count>,<function name>"
+// - "FNF:<number of functions found>"
+// - "FNH:<number of functions hit>"
+// - for each instrumented line:
+// - "DA:<line number>,<execution count>[,<checksum>]
+// - "LH:<number of lines with non-zero execution count>"
+// - "LF:<nubmer of instrumented lines>"
+// - "end_of_record"
+//
+// If the user is exporting summary information only, then the FN, FNDA, and DA
+// lines will not be present.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CoverageExporterLcov.h"
+#include "CoverageReport.h"
+
+using namespace llvm;
+
+namespace {
+
+void renderFunctionSummary(raw_ostream &OS,
+ const FileCoverageSummary &Summary) {
+ OS << "FNF:" << Summary.FunctionCoverage.getNumFunctions() << '\n'
+ << "FNH:" << Summary.FunctionCoverage.getExecuted() << '\n';
+}
+
+void renderFunctions(
+ raw_ostream &OS,
+ const iterator_range<coverage::FunctionRecordIterator> &Functions) {
+ for (const auto &F : Functions) {
+ auto StartLine = F.CountedRegions.front().LineStart;
+ OS << "FN:" << StartLine << ',' << F.Name << '\n';
+ }
+ for (const auto &F : Functions)
+ OS << "FNDA:" << F.ExecutionCount << ',' << F.Name << '\n';
+}
+
+void renderLineExecutionCounts(raw_ostream &OS,
+ const coverage::CoverageData &FileCoverage) {
+ coverage::LineCoverageIterator LCI{FileCoverage, 1};
+ coverage::LineCoverageIterator LCIEnd = LCI.getEnd();
+ for (; LCI != LCIEnd; ++LCI) {
+ const coverage::LineCoverageStats &LCS = *LCI;
+ if (LCS.isMapped()) {
+ OS << "DA:" << LCS.getLine() << ',' << LCS.getExecutionCount() << '\n';
+ }
+ }
+}
+
+void renderLineSummary(raw_ostream &OS, const FileCoverageSummary &Summary) {
+ OS << "LF:" << Summary.LineCoverage.getNumLines() << '\n'
+ << "LH:" << Summary.LineCoverage.getCovered() << '\n';
+}
+
+void renderFile(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
+ const std::string &Filename,
+ const FileCoverageSummary &FileReport, bool ExportSummaryOnly) {
+ OS << "SF:" << Filename << '\n';
+
+ if (!ExportSummaryOnly) {
+ renderFunctions(OS, Coverage.getCoveredFunctions());
+ }
+ renderFunctionSummary(OS, FileReport);
+
+ if (!ExportSummaryOnly) {
+ // Calculate and render detailed coverage information for given file.
+ auto FileCoverage = Coverage.getCoverageForFile(Filename);
+ renderLineExecutionCounts(OS, FileCoverage);
+ }
+ renderLineSummary(OS, FileReport);
+
+ OS << "end_of_record\n";
+}
+
+void renderFiles(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
+ ArrayRef<std::string> SourceFiles,
+ ArrayRef<FileCoverageSummary> FileReports,
+ bool ExportSummaryOnly) {
+ for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I)
+ renderFile(OS, Coverage, SourceFiles[I], FileReports[I], ExportSummaryOnly);
+}
+
+} // end anonymous namespace
+
+void CoverageExporterLcov::renderRoot(const CoverageFilters &IgnoreFilters) {
+ std::vector<std::string> SourceFiles;
+ for (StringRef SF : Coverage.getUniqueSourceFiles()) {
+ if (!IgnoreFilters.matchesFilename(SF))
+ SourceFiles.emplace_back(SF);
+ }
+ renderRoot(SourceFiles);
+}
+
+void CoverageExporterLcov::renderRoot(ArrayRef<std::string> SourceFiles) {
+ FileCoverageSummary Totals = FileCoverageSummary("Totals");
+ auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
+ SourceFiles, Options);
+ renderFiles(OS, Coverage, SourceFiles, FileReports,
+ Options.ExportSummaryOnly);
+}
Added: llvm/trunk/tools/llvm-cov/CoverageExporterLcov.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageExporterLcov.h?rev=346506&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageExporterLcov.h (added)
+++ llvm/trunk/tools/llvm-cov/CoverageExporterLcov.h Fri Nov 9 08:10:44 2018
@@ -0,0 +1,36 @@
+//===- CoverageExporterLcov.h - Code coverage lcov exporter ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements a code coverage exporter for lcov trace file format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_COV_COVERAGEEXPORTERLCOV_H
+#define LLVM_COV_COVERAGEEXPORTERLCOV_H
+
+#include "CoverageExporter.h"
+
+namespace llvm {
+
+class CoverageExporterLcov : public CoverageExporter {
+public:
+ CoverageExporterLcov(const coverage::CoverageMapping &CoverageMapping,
+ const CoverageViewOptions &Options, raw_ostream &OS)
+ : CoverageExporter(CoverageMapping, Options, OS) {}
+
+ /// Render the CoverageMapping object.
+ void renderRoot(const CoverageFilters &IgnoreFilters) override;
+
+ /// Render the CoverageMapping object for specified source files.
+ void renderRoot(ArrayRef<std::string> SourceFiles) override;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_COV_COVERAGEEXPORTERLCOV_H
Modified: llvm/trunk/tools/llvm-cov/CoverageViewOptions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageViewOptions.h?rev=346506&r1=346505&r2=346506&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageViewOptions.h (original)
+++ llvm/trunk/tools/llvm-cov/CoverageViewOptions.h Fri Nov 9 08:10:44 2018
@@ -20,7 +20,8 @@ namespace llvm {
struct CoverageViewOptions {
enum class OutputFormat {
Text,
- HTML
+ HTML,
+ Lcov
};
bool Debug;
Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp?rev=346506&r1=346505&r2=346506&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp Fri Nov 9 08:10:44 2018
@@ -80,6 +80,10 @@ CoveragePrinter::create(const CoverageVi
return llvm::make_unique<CoveragePrinterText>(Opts);
case CoverageViewOptions::OutputFormat::HTML:
return llvm::make_unique<CoveragePrinterHTML>(Opts);
+ case CoverageViewOptions::OutputFormat::Lcov:
+ // Unreachable because CodeCoverage.cpp should terminate with an error
+ // before we get here.
+ llvm_unreachable("Lcov format is not supported!");
}
llvm_unreachable("Unknown coverage output format!");
}
@@ -143,6 +147,10 @@ SourceCoverageView::create(StringRef Sou
case CoverageViewOptions::OutputFormat::HTML:
return llvm::make_unique<SourceCoverageViewHTML>(
SourceName, File, Options, std::move(CoverageInfo));
+ case CoverageViewOptions::OutputFormat::Lcov:
+ // Unreachable because CodeCoverage.cpp should terminate with an error
+ // before we get here.
+ llvm_unreachable("Lcov format is not supported!");
}
llvm_unreachable("Unknown coverage output format!");
}
More information about the llvm-commits
mailing list