diff options
| author | Max Moroz <mmoroz@chromium.org> | 2018-11-09 16:10:44 +0000 |
|---|---|---|
| committer | Max Moroz <mmoroz@chromium.org> | 2018-11-09 16:10:44 +0000 |
| commit | b2091c930b765a1f1b75c9159f49329af59604f9 (patch) | |
| tree | 2cd9a18678670d2096029b255a7577c73dd29bb0 /llvm/tools/llvm-cov/CoverageExporterLcov.cpp | |
| parent | 9cad24a7ee2e61c21b24da6326827bb7dbb04dde (diff) | |
| download | bcm5719-llvm-b2091c930b765a1f1b75c9159f49329af59604f9.tar.gz bcm5719-llvm-b2091c930b765a1f1b75c9159f49329af59604f9.zip | |
[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
llvm-svn: 346506
Diffstat (limited to 'llvm/tools/llvm-cov/CoverageExporterLcov.cpp')
| -rw-r--r-- | llvm/tools/llvm-cov/CoverageExporterLcov.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/llvm/tools/llvm-cov/CoverageExporterLcov.cpp b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp new file mode 100644 index 00000000000..d149ba1a4c8 --- /dev/null +++ b/llvm/tools/llvm-cov/CoverageExporterLcov.cpp @@ -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); +} |

