1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[llvm-cov] Refactor "export" command implementation and add support for SOURCES.

Summary: Define an interface for Exporter + split JSON exporter into .h and .cpp.

Reviewers: vsk, morehouse

Reviewed By: vsk

Subscribers: llvm-commits, Dor1s, kcc

Differential Revision: https://reviews.llvm.org/D41600

llvm-svn: 321815
This commit is contained in:
Max Moroz 2018-01-04 19:33:29 +00:00
parent 380fab0c3a
commit d1429a97f5
7 changed files with 492 additions and 368 deletions

View File

@ -361,14 +361,15 @@ EXPORT COMMAND
SYNOPSIS
^^^^^^^^
:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]]
:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] [*SOURCES*]
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.
*PROFILE* as JSON. It 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,
see :ref:`llvm-cov-show`.

View File

@ -20,6 +20,20 @@ SHOW: {{.*}}sources_specified{{.*}}
SHOW: {{.*}}sources_specified{{.*}}
SHOW: {{.*}}sources_specified{{.*}}
# Test "export" command. Use a temp .json file as output is a single line.
RUN: llvm-cov export -instr-profile %S/Inputs/sources_specified/main.profdata \
RUN: -path-equivalence=/tmp,%S/Inputs \
RUN: %S/Inputs/sources_specified/main.covmapping \
RUN: %S/Inputs/sources_specified/main.cc %S/Inputs/sources_specified/extra \
RUN: > %t.export.json
RUN: not grep '"filename":"/tmp/sources_specified/abs.h"' %t.export.json
RUN: grep '"filename":"/tmp/sources_specified/main.cc"' %t.export.json
RUN: grep '"filename":"/tmp/sources_specified/extra/dec.h"' %t.export.json
RUN: grep '"filename":"/tmp/sources_specified/extra/inc.h"' %t.export.json
Instructions for regenerating the test:
# cd %S/Inputs/sources_specified

View File

@ -13,6 +13,7 @@
//
//===----------------------------------------------------------------------===//
#include "CoverageExporterJson.h"
#include "CoverageFilters.h"
#include "CoverageReport.h"
#include "CoverageSummaryInfo.h"
@ -113,14 +114,14 @@ private:
typedef llvm::function_ref<int(int, const char **)> CommandLineParserType;
int show(int argc, const char **argv,
CommandLineParserType commandLineParser);
int report(int argc, const char **argv,
int doShow(int argc, const char **argv,
CommandLineParserType commandLineParser);
int export_(int argc, const char **argv,
CommandLineParserType commandLineParser);
int doReport(int argc, const char **argv,
CommandLineParserType commandLineParser);
int doExport(int argc, const char **argv,
CommandLineParserType commandLineParser);
std::vector<StringRef> ObjectFilenames;
CoverageViewOptions ViewOpts;
@ -755,17 +756,17 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
switch (Cmd) {
case Show:
return show(argc, argv, commandLineParser);
return doShow(argc, argv, commandLineParser);
case Report:
return report(argc, argv, commandLineParser);
return doReport(argc, argv, commandLineParser);
case Export:
return export_(argc, argv, commandLineParser);
return doExport(argc, argv, commandLineParser);
}
return 0;
}
int CodeCoverageTool::show(int argc, const char **argv,
CommandLineParserType commandLineParser) {
int CodeCoverageTool::doShow(int argc, const char **argv,
CommandLineParserType commandLineParser) {
cl::OptionCategory ViewCategory("Viewing options");
@ -932,8 +933,8 @@ int CodeCoverageTool::show(int argc, const char **argv,
return 0;
}
int CodeCoverageTool::report(int argc, const char **argv,
CommandLineParserType commandLineParser) {
int CodeCoverageTool::doReport(int argc, const char **argv,
CommandLineParserType commandLineParser) {
cl::opt<bool> ShowFunctionSummaries(
"show-functions", cl::Optional, cl::init(false),
cl::desc("Show coverage summaries for each function"));
@ -969,8 +970,8 @@ int CodeCoverageTool::report(int argc, const char **argv,
return 0;
}
int CodeCoverageTool::export_(int argc, const char **argv,
CommandLineParserType commandLineParser) {
int CodeCoverageTool::doExport(int argc, const char **argv,
CommandLineParserType commandLineParser) {
auto Err = commandLineParser(argc, argv);
if (Err)
@ -987,7 +988,12 @@ int CodeCoverageTool::export_(int argc, const char **argv,
return 1;
}
exportCoverageDataToJson(*Coverage.get(), ViewOpts, outs());
auto Exporter = CoverageExporterJson(*Coverage.get(), ViewOpts, outs());
if (SourceFiles.empty())
Exporter.renderRoot();
else
Exporter.renderRoot(SourceFiles);
return 0;
}

View File

@ -0,0 +1,51 @@
//===- CoverageExporter.h - Code coverage exporter ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class defines a code coverage exporter interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_COV_COVERAGEEXPORTER_H
#define LLVM_COV_COVERAGEEXPORTER_H
#include "CoverageSummaryInfo.h"
#include "CoverageViewOptions.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
namespace llvm {
/// \brief Exports the code coverage information.
class CoverageExporter {
protected:
/// \brief The full CoverageMapping object to export.
const coverage::CoverageMapping &Coverage;
/// \brief The options passed to the tool.
const CoverageViewOptions &Options;
/// \brief Output stream to print JSON to.
raw_ostream &OS;
CoverageExporter(const coverage::CoverageMapping &CoverageMapping,
const CoverageViewOptions &Options, raw_ostream &OS)
: Coverage(CoverageMapping), Options(Options), OS(OS) {}
public:
virtual ~CoverageExporter(){};
/// \brief Render the CoverageMapping object.
virtual void renderRoot() = 0;
/// \brief Render the CoverageMapping object for specified source files.
virtual void renderRoot(const std::vector<std::string> &SourceFiles) = 0;
};
} // end namespace llvm
#endif // LLVM_COV_COVERAGEEXPORTER_H

View File

@ -41,11 +41,8 @@
//
//===----------------------------------------------------------------------===//
#include "CoverageExporterJson.h"
#include "CoverageReport.h"
#include "CoverageSummaryInfo.h"
#include "CoverageViewOptions.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include <stack>
/// \brief The semantic version combined as a string.
#define LLVM_COVERAGE_EXPORT_JSON_STR "2.0.0"
@ -54,381 +51,328 @@
#define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export"
using namespace llvm;
using namespace coverage;
class CoverageExporterJson {
const CoverageViewOptions &Options;
CoverageExporterJson::CoverageExporterJson(
const coverage::CoverageMapping &CoverageMapping,
const CoverageViewOptions &Options, raw_ostream &OS)
: CoverageExporter(CoverageMapping, Options, OS) {
State.push(JsonState::None);
}
/// \brief Output stream to print JSON to.
raw_ostream &OS;
void CoverageExporterJson::emitSerialized(const int64_t Value) { OS << Value; }
/// \brief The full CoverageMapping object to export.
const CoverageMapping &Coverage;
/// \brief States that the JSON rendering machine can be in.
enum JsonState { None, NonEmptyElement, EmptyElement };
/// \brief Tracks state of the JSON output.
std::stack<JsonState> State;
/// \brief Emit a serialized scalar.
void emitSerialized(const int64_t Value) { OS << Value; }
/// \brief Emit a serialized string.
void emitSerialized(const std::string &Value) {
OS << "\"";
for (char C : Value) {
if (C != '\\')
OS << C;
else
OS << "\\\\";
}
OS << "\"";
void CoverageExporterJson::emitSerialized(const std::string &Value) {
OS << "\"";
for (char C : Value) {
if (C != '\\')
OS << C;
else
OS << "\\\\";
}
OS << "\"";
}
/// \brief Emit a comma if there is a previous element to delimit.
void emitComma() {
if (State.top() == JsonState::NonEmptyElement) {
OS << ",";
} else if (State.top() == JsonState::EmptyElement) {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
State.push(JsonState::NonEmptyElement);
}
}
/// \brief Emit a starting dictionary/object character.
void emitDictStart() {
emitComma();
State.push(JsonState::EmptyElement);
OS << "{";
}
/// \brief Emit a dictionary/object key but no value.
void emitDictKey(const std::string &Key) {
emitComma();
emitSerialized(Key);
OS << ":";
void CoverageExporterJson::emitComma() {
if (State.top() == JsonState::NonEmptyElement) {
OS << ",";
} else if (State.top() == JsonState::EmptyElement) {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
// We do not want to emit a comma after this key.
State.push(JsonState::EmptyElement);
State.push(JsonState::NonEmptyElement);
}
}
/// \brief Emit a dictionary/object key/value pair.
template <typename V>
void emitDictElement(const std::string &Key, const V &Value) {
emitComma();
emitSerialized(Key);
OS << ":";
emitSerialized(Value);
}
void CoverageExporterJson::emitDictStart() {
emitComma();
State.push(JsonState::EmptyElement);
OS << "{";
}
/// \brief Emit a closing dictionary/object character.
void emitDictEnd() {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
OS << "}";
}
void CoverageExporterJson::emitDictKey(const std::string &Key) {
emitComma();
emitSerialized(Key);
OS << ":";
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
/// \brief Emit a starting array character.
void emitArrayStart() {
emitComma();
State.push(JsonState::EmptyElement);
OS << "[";
}
// We do not want to emit a comma after this key.
State.push(JsonState::EmptyElement);
}
/// \brief Emit an array element.
template <typename V> void emitArrayElement(const V &Value) {
emitComma();
emitSerialized(Value);
}
void CoverageExporterJson::emitDictEnd() {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
OS << "}";
}
/// \brief emit a closing array character.
void emitArrayEnd() {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
OS << "]";
}
void CoverageExporterJson::emitArrayStart() {
emitComma();
State.push(JsonState::EmptyElement);
OS << "[";
}
/// \brief Render the CoverageMapping object.
void renderRoot() {
// Start Root of JSON object.
emitDictStart();
void CoverageExporterJson::emitArrayEnd() {
State.pop();
assert((State.size() >= 1) && "Closed too many JSON elements");
OS << "]";
}
emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
emitDictKey("data");
void CoverageExporterJson::renderRoot() {
std::vector<std::string> SourceFiles;
for (StringRef SF : Coverage.getUniqueSourceFiles())
SourceFiles.emplace_back(SF);
renderRoot(SourceFiles);
}
// Start List of Exports.
emitArrayStart();
void CoverageExporterJson::renderRoot(
const std::vector<std::string> &SourceFiles) {
// Start Root of JSON object.
emitDictStart();
// Start Export.
emitDictStart();
emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
emitDictKey("data");
emitDictKey("files");
// Start List of Exports.
emitArrayStart();
FileCoverageSummary Totals = FileCoverageSummary("Totals");
std::vector<std::string> SourceFiles;
for (StringRef SF : Coverage.getUniqueSourceFiles())
SourceFiles.emplace_back(SF);
auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
SourceFiles, Options);
renderFiles(SourceFiles, FileReports);
// Start Export.
emitDictStart();
// Skip functions-level information for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("functions");
renderFunctions(Coverage.getCoveredFunctions());
}
emitDictKey("files");
emitDictKey("totals");
renderSummary(Totals);
// End Export.
emitDictEnd();
// End List of Exports.
emitArrayEnd();
// End Root of JSON Object.
emitDictEnd();
assert((State.top() == JsonState::None) &&
"All Elements In JSON were Closed");
}
/// \brief Render an array of all the given functions.
void
renderFunctions(const iterator_range<FunctionRecordIterator> &Functions) {
// Start List of Functions.
emitArrayStart();
for (const auto &Function : Functions) {
// Start Function.
emitDictStart();
emitDictElement("name", Function.Name);
emitDictElement("count", Function.ExecutionCount);
emitDictKey("regions");
renderRegions(Function.CountedRegions);
emitDictKey("filenames");
// Start Filenames for Function.
emitArrayStart();
for (const auto &FileName : Function.Filenames)
emitArrayElement(FileName);
// End Filenames for Function.
emitArrayEnd();
// End Function.
emitDictEnd();
}
// End List of Functions.
emitArrayEnd();
}
/// \brief Render an array of all the source files, also pass back a Summary.
void renderFiles(ArrayRef<std::string> SourceFiles,
ArrayRef<FileCoverageSummary> FileReports) {
// Start List of Files.
emitArrayStart();
for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) {
// Render the file.
auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]);
renderFile(FileCoverage, FileReports[I]);
}
// End List of Files.
emitArrayEnd();
}
/// \brief Render a single file.
void renderFile(const CoverageData &FileCoverage,
const FileCoverageSummary &FileReport) {
// Start File.
emitDictStart();
emitDictElement("filename", FileCoverage.getFilename());
// Skip segments and expansions for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("segments");
// Start List of Segments.
emitArrayStart();
for (const auto &Segment : FileCoverage)
renderSegment(Segment);
// End List of Segments.
emitArrayEnd();
emitDictKey("expansions");
// Start List of Expansions.
emitArrayStart();
for (const auto &Expansion : FileCoverage.getExpansions())
renderExpansion(Expansion);
// End List of Expansions.
emitArrayEnd();
}
emitDictKey("summary");
renderSummary(FileReport);
// End File.
emitDictEnd();
}
/// \brief Render a CoverageSegment.
void renderSegment(const CoverageSegment &Segment) {
// Start Segment.
emitArrayStart();
emitArrayElement(Segment.Line);
emitArrayElement(Segment.Col);
emitArrayElement(Segment.Count);
emitArrayElement(Segment.HasCount);
emitArrayElement(Segment.IsRegionEntry);
// End Segment.
emitArrayEnd();
}
/// \brief Render an ExpansionRecord.
void renderExpansion(const ExpansionRecord &Expansion) {
// Start Expansion.
emitDictStart();
// Mark the beginning and end of this expansion in the source file.
emitDictKey("source_region");
renderRegion(Expansion.Region);
// Enumerate the coverage information for the expansion.
emitDictKey("target_regions");
renderRegions(Expansion.Function.CountedRegions);
emitDictKey("filenames");
// Start List of Filenames to map the fileIDs.
emitArrayStart();
for (const auto &Filename : Expansion.Function.Filenames)
emitArrayElement(Filename);
// End List of Filenames.
emitArrayEnd();
// End Expansion.
emitDictEnd();
}
/// \brief Render a list of CountedRegions.
void renderRegions(ArrayRef<CountedRegion> Regions) {
// Start List of Regions.
emitArrayStart();
for (const auto &Region : Regions)
renderRegion(Region);
// End List of Regions.
emitArrayEnd();
}
/// \brief Render a single CountedRegion.
void renderRegion(const CountedRegion &Region) {
// Start CountedRegion.
emitArrayStart();
emitArrayElement(Region.LineStart);
emitArrayElement(Region.ColumnStart);
emitArrayElement(Region.LineEnd);
emitArrayElement(Region.ColumnEnd);
emitArrayElement(Region.ExecutionCount);
emitArrayElement(Region.FileID);
emitArrayElement(Region.ExpandedFileID);
emitArrayElement(Region.Kind);
// End CountedRegion.
emitArrayEnd();
}
/// \brief Render a FileCoverageSummary.
void renderSummary(const FileCoverageSummary &Summary) {
// Start Summary for the file.
emitDictStart();
emitDictKey("lines");
// Start Line Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.LineCoverage.getNumLines());
emitDictElement("covered", Summary.LineCoverage.getCovered());
emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
// End Line Coverage Summary.
emitDictEnd();
FileCoverageSummary Totals = FileCoverageSummary("Totals");
auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
SourceFiles, Options);
renderFiles(SourceFiles, FileReports);
// Skip functions-level information for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("functions");
renderFunctions(Coverage.getCoveredFunctions());
}
// Start Function Coverage Summary.
emitDictKey("totals");
renderSummary(Totals);
// End Export.
emitDictEnd();
// End List of Exports.
emitArrayEnd();
// End Root of JSON Object.
emitDictEnd();
assert((State.top() == JsonState::None) &&
"All Elements In JSON were Closed");
}
void CoverageExporterJson::renderFunctions(
const iterator_range<coverage::FunctionRecordIterator> &Functions) {
// Start List of Functions.
emitArrayStart();
for (const auto &Function : Functions) {
// Start Function.
emitDictStart();
emitDictElement("count", Summary.FunctionCoverage.getNumFunctions());
emitDictElement("covered", Summary.FunctionCoverage.getExecuted());
emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
// End Function Coverage Summary.
emitDictEnd();
emitDictKey("instantiations");
// Start Instantiation Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions());
emitDictElement("covered", Summary.InstantiationCoverage.getExecuted());
emitDictElement("percent",
Summary.InstantiationCoverage.getPercentCovered());
// End Function Coverage Summary.
emitDictEnd();
emitDictElement("name", Function.Name);
emitDictElement("count", Function.ExecutionCount);
emitDictKey("regions");
// Start Region Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.RegionCoverage.getNumRegions());
emitDictElement("covered", Summary.RegionCoverage.getCovered());
emitDictElement("notcovered",
Summary.RegionCoverage.getNumRegions() -
Summary.RegionCoverage.getCovered());
emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
// End Region Coverage Summary.
emitDictEnd();
renderRegions(Function.CountedRegions);
// End Summary for the file.
emitDictKey("filenames");
// Start Filenames for Function.
emitArrayStart();
for (const auto &FileName : Function.Filenames)
emitArrayElement(FileName);
// End Filenames for Function.
emitArrayEnd();
// End Function.
emitDictEnd();
}
public:
CoverageExporterJson(const CoverageMapping &CoverageMapping,
const CoverageViewOptions &Options, raw_ostream &OS)
: Options(Options), OS(OS), Coverage(CoverageMapping) {
State.push(JsonState::None);
}
/// \brief Print the CoverageMapping.
void print() { renderRoot(); }
};
/// \brief Export the given CoverageMapping to a JSON Format.
void exportCoverageDataToJson(const CoverageMapping &CoverageMapping,
const CoverageViewOptions &Options,
raw_ostream &OS) {
auto Exporter = CoverageExporterJson(CoverageMapping, Options, OS);
Exporter.print();
// End List of Functions.
emitArrayEnd();
}
void CoverageExporterJson::renderFiles(
ArrayRef<std::string> SourceFiles,
ArrayRef<FileCoverageSummary> FileReports) {
// Start List of Files.
emitArrayStart();
for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) {
// Render the file.
auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]);
renderFile(FileCoverage, FileReports[I]);
}
// End List of Files.
emitArrayEnd();
}
void CoverageExporterJson::renderFile(
const coverage::CoverageData &FileCoverage,
const FileCoverageSummary &FileReport) {
// Start File.
emitDictStart();
emitDictElement("filename", FileCoverage.getFilename());
// Skip segments and expansions for summary-only export mode.
if (!Options.ExportSummaryOnly) {
emitDictKey("segments");
// Start List of Segments.
emitArrayStart();
for (const auto &Segment : FileCoverage)
renderSegment(Segment);
// End List of Segments.
emitArrayEnd();
emitDictKey("expansions");
// Start List of Expansions.
emitArrayStart();
for (const auto &Expansion : FileCoverage.getExpansions())
renderExpansion(Expansion);
// End List of Expansions.
emitArrayEnd();
}
emitDictKey("summary");
renderSummary(FileReport);
// End File.
emitDictEnd();
}
void CoverageExporterJson::renderSegment(
const coverage::CoverageSegment &Segment) {
// Start Segment.
emitArrayStart();
emitArrayElement(Segment.Line);
emitArrayElement(Segment.Col);
emitArrayElement(Segment.Count);
emitArrayElement(Segment.HasCount);
emitArrayElement(Segment.IsRegionEntry);
// End Segment.
emitArrayEnd();
}
void CoverageExporterJson::renderExpansion(
const coverage::ExpansionRecord &Expansion) {
// Start Expansion.
emitDictStart();
// Mark the beginning and end of this expansion in the source file.
emitDictKey("source_region");
renderRegion(Expansion.Region);
// Enumerate the coverage information for the expansion.
emitDictKey("target_regions");
renderRegions(Expansion.Function.CountedRegions);
emitDictKey("filenames");
// Start List of Filenames to map the fileIDs.
emitArrayStart();
for (const auto &Filename : Expansion.Function.Filenames)
emitArrayElement(Filename);
// End List of Filenames.
emitArrayEnd();
// End Expansion.
emitDictEnd();
}
void CoverageExporterJson::renderRegions(
ArrayRef<coverage::CountedRegion> Regions) {
// Start List of Regions.
emitArrayStart();
for (const auto &Region : Regions)
renderRegion(Region);
// End List of Regions.
emitArrayEnd();
}
void CoverageExporterJson::renderRegion(const coverage::CountedRegion &Region) {
// Start CountedRegion.
emitArrayStart();
emitArrayElement(Region.LineStart);
emitArrayElement(Region.ColumnStart);
emitArrayElement(Region.LineEnd);
emitArrayElement(Region.ColumnEnd);
emitArrayElement(Region.ExecutionCount);
emitArrayElement(Region.FileID);
emitArrayElement(Region.ExpandedFileID);
emitArrayElement(Region.Kind);
// End CountedRegion.
emitArrayEnd();
}
void CoverageExporterJson::renderSummary(const FileCoverageSummary &Summary) {
// Start Summary for the file.
emitDictStart();
emitDictKey("lines");
// Start Line Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.LineCoverage.getNumLines());
emitDictElement("covered", Summary.LineCoverage.getCovered());
emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
// End Line Coverage Summary.
emitDictEnd();
emitDictKey("functions");
// Start Function Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.FunctionCoverage.getNumFunctions());
emitDictElement("covered", Summary.FunctionCoverage.getExecuted());
emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
// End Function Coverage Summary.
emitDictEnd();
emitDictKey("instantiations");
// Start Instantiation Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions());
emitDictElement("covered", Summary.InstantiationCoverage.getExecuted());
emitDictElement("percent", Summary.InstantiationCoverage.getPercentCovered());
// End Function Coverage Summary.
emitDictEnd();
emitDictKey("regions");
// Start Region Coverage Summary.
emitDictStart();
emitDictElement("count", Summary.RegionCoverage.getNumRegions());
emitDictElement("covered", Summary.RegionCoverage.getCovered());
emitDictElement("notcovered", Summary.RegionCoverage.getNumRegions() -
Summary.RegionCoverage.getCovered());
emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
// End Region Coverage Summary.
emitDictEnd();
// End Summary for the file.
emitDictEnd();
}

View File

@ -0,0 +1,108 @@
//===- CoverageExporterJson.h - Code coverage JSON 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 JSON format.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_COV_COVERAGEEXPORTERJSON_H
#define LLVM_COV_COVERAGEEXPORTERJSON_H
#include "CoverageExporter.h"
#include <stack>
namespace llvm {
class CoverageExporterJson : public CoverageExporter {
/// \brief States that the JSON rendering machine can be in.
enum JsonState { None, NonEmptyElement, EmptyElement };
/// \brief Tracks state of the JSON output.
std::stack<JsonState> State;
/// \brief Emit a serialized scalar.
void emitSerialized(const int64_t Value);
/// \brief Emit a serialized string.
void emitSerialized(const std::string &Value);
/// \brief Emit a comma if there is a previous element to delimit.
void emitComma();
/// \brief Emit a starting dictionary/object character.
void emitDictStart();
/// \brief Emit a dictionary/object key but no value.
void emitDictKey(const std::string &Key);
/// \brief Emit a dictionary/object key/value pair.
template <typename V>
void emitDictElement(const std::string &Key, const V &Value) {
emitComma();
emitSerialized(Key);
OS << ":";
emitSerialized(Value);
}
/// \brief Emit a closing dictionary/object character.
void emitDictEnd();
/// \brief Emit a starting array character.
void emitArrayStart();
/// \brief Emit an array element.
template <typename V> void emitArrayElement(const V &Value) {
emitComma();
emitSerialized(Value);
}
/// \brief emit a closing array character.
void emitArrayEnd();
/// \brief Render an array of all the given functions.
void renderFunctions(
const iterator_range<coverage::FunctionRecordIterator> &Functions);
/// \brief Render an array of all the source files, also pass back a Summary.
void renderFiles(ArrayRef<std::string> SourceFiles,
ArrayRef<FileCoverageSummary> FileReports);
/// \brief Render a single file.
void renderFile(const coverage::CoverageData &FileCoverage,
const FileCoverageSummary &FileReport);
/// \brief Render a CoverageSegment.
void renderSegment(const coverage::CoverageSegment &Segment);
/// \brief Render an ExpansionRecord.
void renderExpansion(const coverage::ExpansionRecord &Expansion);
/// \brief Render a list of CountedRegions.
void renderRegions(ArrayRef<coverage::CountedRegion> Regions);
/// \brief Render a single CountedRegion.
void renderRegion(const coverage::CountedRegion &Region);
/// \brief Render a FileCoverageSummary.
void renderSummary(const FileCoverageSummary &Summary);
public:
CoverageExporterJson(const coverage::CoverageMapping &CoverageMapping,
const CoverageViewOptions &Options, raw_ostream &OS);
/// \brief Render the CoverageMapping object.
void renderRoot() override;
/// \brief Render the CoverageMapping object for specified source files.
void renderRoot(const std::vector<std::string> &SourceFiles) override;
};
} // end namespace llvm
#endif // LLVM_COV_COVERAGEEXPORTERJSON_H

View File

@ -1,4 +1,4 @@
//===- CoverageReport.h - Code coverage report ---------------------------===//
//===- CoverageReport.h - Code coverage report ----------------------------===//
//
// The LLVM Compiler Infrastructure
//