You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
15
external/llvm/tools/llvm-cov/CMakeLists.txt
vendored
15
external/llvm/tools/llvm-cov/CMakeLists.txt
vendored
@ -1,15 +0,0 @@
|
||||
set(LLVM_LINK_COMPONENTS core support object coverage profiledata)
|
||||
|
||||
add_llvm_tool(llvm-cov
|
||||
llvm-cov.cpp
|
||||
gcov.cpp
|
||||
CodeCoverage.cpp
|
||||
CoverageExporterJson.cpp
|
||||
CoverageFilters.cpp
|
||||
CoverageReport.cpp
|
||||
CoverageSummaryInfo.cpp
|
||||
SourceCoverageView.cpp
|
||||
SourceCoverageViewHTML.cpp
|
||||
SourceCoverageViewText.cpp
|
||||
TestingSupport.cpp
|
||||
)
|
1008
external/llvm/tools/llvm-cov/CodeCoverage.cpp
vendored
1008
external/llvm/tools/llvm-cov/CodeCoverage.cpp
vendored
File diff suppressed because it is too large
Load Diff
@ -1,434 +0,0 @@
|
||||
//===- CoverageExporterJson.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 JSON.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The json code coverage export follows the following format
|
||||
// Root: dict => Root Element containing metadata
|
||||
// -- Data: array => Homogeneous array of one or more export objects
|
||||
// ---- Export: dict => Json representation of one CoverageMapping
|
||||
// ------ Files: array => List of objects describing coverage for files
|
||||
// -------- File: dict => Coverage for a single file
|
||||
// ---------- Segments: array => List of Segments contained in the file
|
||||
// ------------ Segment: dict => Describes a segment of the file with a counter
|
||||
// ---------- Expansions: array => List of expansion records
|
||||
// ------------ Expansion: dict => Object that descibes a single expansion
|
||||
// -------------- CountedRegion: dict => The region to be expanded
|
||||
// -------------- TargetRegions: array => List of Regions in the expansion
|
||||
// ---------------- CountedRegion: dict => Single Region in the expansion
|
||||
// ---------- Summary: dict => Object summarizing the coverage for this file
|
||||
// ------------ LineCoverage: dict => Object summarizing line coverage
|
||||
// ------------ FunctionCoverage: dict => Object summarizing function coverage
|
||||
// ------------ RegionCoverage: dict => Object summarizing region coverage
|
||||
// ------ Functions: array => List of objects describing coverage for functions
|
||||
// -------- Function: dict => Coverage info for a single function
|
||||
// ---------- Filenames: array => List of filenames that the function relates to
|
||||
// ---- Summary: dict => Object summarizing the coverage for the entire binary
|
||||
// ------ LineCoverage: dict => Object summarizing line coverage
|
||||
// ------ FunctionCoverage: dict => Object summarizing function coverage
|
||||
// ------ InstantiationCoverage: dict => Object summarizing inst. coverage
|
||||
// ------ RegionCoverage: dict => Object summarizing region coverage
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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"
|
||||
|
||||
/// \brief Unique type identifier for JSON coverage export.
|
||||
#define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace coverage;
|
||||
|
||||
class CoverageExporterJson {
|
||||
const CoverageViewOptions &Options;
|
||||
|
||||
/// \brief Output stream to print JSON to.
|
||||
raw_ostream &OS;
|
||||
|
||||
/// \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 << "\"";
|
||||
}
|
||||
|
||||
/// \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 << ":";
|
||||
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);
|
||||
}
|
||||
|
||||
/// \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() {
|
||||
State.pop();
|
||||
assert((State.size() >= 1) && "Closed too many JSON elements");
|
||||
OS << "}";
|
||||
}
|
||||
|
||||
/// \brief Emit a starting array character.
|
||||
void emitArrayStart() {
|
||||
emitComma();
|
||||
State.push(JsonState::EmptyElement);
|
||||
OS << "[";
|
||||
}
|
||||
|
||||
/// \brief Emit an array element.
|
||||
template <typename V> void emitArrayElement(const V &Value) {
|
||||
emitComma();
|
||||
emitSerialized(Value);
|
||||
}
|
||||
|
||||
/// \brief emit a closing array character.
|
||||
void emitArrayEnd() {
|
||||
State.pop();
|
||||
assert((State.size() >= 1) && "Closed too many JSON elements");
|
||||
OS << "]";
|
||||
}
|
||||
|
||||
/// \brief Render the CoverageMapping object.
|
||||
void renderRoot() {
|
||||
// Start Root of JSON object.
|
||||
emitDictStart();
|
||||
|
||||
emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
|
||||
emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
|
||||
emitDictKey("data");
|
||||
|
||||
// Start List of Exports.
|
||||
emitArrayStart();
|
||||
|
||||
// Start Export.
|
||||
emitDictStart();
|
||||
|
||||
emitDictKey("files");
|
||||
|
||||
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);
|
||||
|
||||
// Skip functions-level information for summary-only export mode.
|
||||
if (!Options.ExportSummaryOnly) {
|
||||
emitDictKey("functions");
|
||||
renderFunctions(Coverage.getCoveredFunctions());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
74
external/llvm/tools/llvm-cov/CoverageFilters.cpp
vendored
74
external/llvm/tools/llvm-cov/CoverageFilters.cpp
vendored
@ -1,74 +0,0 @@
|
||||
//===- CoverageFilters.cpp - Function coverage mapping filters ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// These classes provide filtering for function coverage mapping records.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoverageFilters.h"
|
||||
#include "CoverageSummaryInfo.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
bool NameCoverageFilter::matches(
|
||||
const coverage::CoverageMapping &,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
StringRef FuncName = Function.Name;
|
||||
return FuncName.find(Name) != StringRef::npos;
|
||||
}
|
||||
|
||||
bool NameRegexCoverageFilter::matches(
|
||||
const coverage::CoverageMapping &,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
return llvm::Regex(Regex).match(Function.Name);
|
||||
}
|
||||
|
||||
bool NameWhitelistCoverageFilter::matches(
|
||||
const coverage::CoverageMapping &,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
return Whitelist.inSection("llvmcov", "whitelist_fun", Function.Name);
|
||||
}
|
||||
|
||||
bool RegionCoverageFilter::matches(
|
||||
const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
return PassesThreshold(FunctionCoverageSummary::get(CM, Function)
|
||||
.RegionCoverage.getPercentCovered());
|
||||
}
|
||||
|
||||
bool LineCoverageFilter::matches(
|
||||
const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
return PassesThreshold(FunctionCoverageSummary::get(CM, Function)
|
||||
.LineCoverage.getPercentCovered());
|
||||
}
|
||||
|
||||
void CoverageFilters::push_back(std::unique_ptr<CoverageFilter> Filter) {
|
||||
Filters.push_back(std::move(Filter));
|
||||
}
|
||||
|
||||
bool CoverageFilters::matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
for (const auto &Filter : Filters) {
|
||||
if (Filter->matches(CM, Function))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CoverageFiltersMatchAll::matches(
|
||||
const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
for (const auto &Filter : Filters) {
|
||||
if (!Filter->matches(CM, Function))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
149
external/llvm/tools/llvm-cov/CoverageFilters.h
vendored
149
external/llvm/tools/llvm-cov/CoverageFilters.h
vendored
@ -1,149 +0,0 @@
|
||||
//===- CoverageFilters.h - Function coverage mapping filters --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// These classes provide filtering for function coverage mapping records.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_COVERAGEFILTERS_H
|
||||
#define LLVM_COV_COVERAGEFILTERS_H
|
||||
|
||||
#include "CoverageSummaryInfo.h"
|
||||
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
|
||||
#include "llvm/Support/SpecialCaseList.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Matches specific functions that pass the requirement of this filter.
|
||||
class CoverageFilter {
|
||||
public:
|
||||
virtual ~CoverageFilter() {}
|
||||
|
||||
/// \brief Return true if the function passes the requirements of this filter.
|
||||
virtual bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Matches functions that contain a specific string in their name.
|
||||
class NameCoverageFilter : public CoverageFilter {
|
||||
StringRef Name;
|
||||
|
||||
public:
|
||||
NameCoverageFilter(StringRef Name) : Name(Name) {}
|
||||
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
/// \brief Matches functions whose name matches a certain regular expression.
|
||||
class NameRegexCoverageFilter : public CoverageFilter {
|
||||
StringRef Regex;
|
||||
|
||||
public:
|
||||
NameRegexCoverageFilter(StringRef Regex) : Regex(Regex) {}
|
||||
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
/// \brief Matches functions whose name appears in a SpecialCaseList in the
|
||||
/// whitelist_fun section.
|
||||
class NameWhitelistCoverageFilter : public CoverageFilter {
|
||||
const SpecialCaseList &Whitelist;
|
||||
|
||||
public:
|
||||
NameWhitelistCoverageFilter(const SpecialCaseList &Whitelist)
|
||||
: Whitelist(Whitelist) {}
|
||||
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
/// \brief Matches numbers that pass a certain threshold.
|
||||
template <typename T> class StatisticThresholdFilter {
|
||||
public:
|
||||
enum Operation { LessThan, GreaterThan };
|
||||
|
||||
protected:
|
||||
Operation Op;
|
||||
T Threshold;
|
||||
|
||||
StatisticThresholdFilter(Operation Op, T Threshold)
|
||||
: Op(Op), Threshold(Threshold) {}
|
||||
|
||||
/// \brief Return true if the given number is less than
|
||||
/// or greater than the certain threshold.
|
||||
bool PassesThreshold(T Value) const {
|
||||
switch (Op) {
|
||||
case LessThan:
|
||||
return Value < Threshold;
|
||||
case GreaterThan:
|
||||
return Value > Threshold;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Matches functions whose region coverage percentage
|
||||
/// is above/below a certain percentage.
|
||||
class RegionCoverageFilter : public CoverageFilter,
|
||||
public StatisticThresholdFilter<double> {
|
||||
public:
|
||||
RegionCoverageFilter(Operation Op, double Threshold)
|
||||
: StatisticThresholdFilter(Op, Threshold) {}
|
||||
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
/// \brief Matches functions whose line coverage percentage
|
||||
/// is above/below a certain percentage.
|
||||
class LineCoverageFilter : public CoverageFilter,
|
||||
public StatisticThresholdFilter<double> {
|
||||
public:
|
||||
LineCoverageFilter(Operation Op, double Threshold)
|
||||
: StatisticThresholdFilter(Op, Threshold) {}
|
||||
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
/// \brief A collection of filters.
|
||||
/// Matches functions that match any filters contained
|
||||
/// in an instance of this class.
|
||||
class CoverageFilters : public CoverageFilter {
|
||||
protected:
|
||||
std::vector<std::unique_ptr<CoverageFilter>> Filters;
|
||||
|
||||
public:
|
||||
/// \brief Append a filter to this collection.
|
||||
void push_back(std::unique_ptr<CoverageFilter> Filter);
|
||||
|
||||
bool empty() const { return Filters.empty(); }
|
||||
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
/// \brief A collection of filters.
|
||||
/// Matches functions that match all of the filters contained
|
||||
/// in an instance of this class.
|
||||
class CoverageFiltersMatchAll : public CoverageFilters {
|
||||
public:
|
||||
bool matches(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) const override;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_COV_COVERAGEFILTERS_H
|
426
external/llvm/tools/llvm-cov/CoverageReport.cpp
vendored
426
external/llvm/tools/llvm-cov/CoverageReport.cpp
vendored
@ -1,426 +0,0 @@
|
||||
//===- CoverageReport.cpp - Code coverage report -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class implements rendering of a code coverage report.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoverageReport.h"
|
||||
#include "RenderingSupport.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include <numeric>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Helper struct which prints trimmed and aligned columns.
|
||||
struct Column {
|
||||
enum TrimKind { NoTrim, WidthTrim, RightTrim };
|
||||
|
||||
enum AlignmentKind { LeftAlignment, RightAlignment };
|
||||
|
||||
StringRef Str;
|
||||
unsigned Width;
|
||||
TrimKind Trim;
|
||||
AlignmentKind Alignment;
|
||||
|
||||
Column(StringRef Str, unsigned Width)
|
||||
: Str(Str), Width(Width), Trim(WidthTrim), Alignment(LeftAlignment) {}
|
||||
|
||||
Column &set(TrimKind Value) {
|
||||
Trim = Value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Column &set(AlignmentKind Value) {
|
||||
Alignment = Value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void render(raw_ostream &OS) const {
|
||||
if (Str.size() <= Width) {
|
||||
if (Alignment == RightAlignment) {
|
||||
OS.indent(Width - Str.size());
|
||||
OS << Str;
|
||||
return;
|
||||
}
|
||||
OS << Str;
|
||||
OS.indent(Width - Str.size());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Trim) {
|
||||
case NoTrim:
|
||||
OS << Str;
|
||||
break;
|
||||
case WidthTrim:
|
||||
OS << Str.substr(0, Width);
|
||||
break;
|
||||
case RightTrim:
|
||||
OS << Str.substr(0, Width - 3) << "...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Column &Value) {
|
||||
Value.render(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
Column column(StringRef Str, unsigned Width) { return Column(Str, Width); }
|
||||
|
||||
template <typename T>
|
||||
Column column(StringRef Str, unsigned Width, const T &Value) {
|
||||
return Column(Str, Width).set(Value);
|
||||
}
|
||||
|
||||
// Specify the default column widths.
|
||||
size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10,
|
||||
16, 16, 10, 12, 18, 10};
|
||||
size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8};
|
||||
|
||||
/// \brief Adjust column widths to fit long file paths and function names.
|
||||
void adjustColumnWidths(ArrayRef<StringRef> Files,
|
||||
ArrayRef<StringRef> Functions) {
|
||||
for (StringRef Filename : Files)
|
||||
FileReportColumns[0] = std::max(FileReportColumns[0], Filename.size());
|
||||
for (StringRef Funcname : Functions)
|
||||
FunctionReportColumns[0] =
|
||||
std::max(FunctionReportColumns[0], Funcname.size());
|
||||
}
|
||||
|
||||
/// \brief Prints a horizontal divider long enough to cover the given column
|
||||
/// widths.
|
||||
void renderDivider(ArrayRef<size_t> ColumnWidths, raw_ostream &OS) {
|
||||
size_t Length = std::accumulate(ColumnWidths.begin(), ColumnWidths.end(), 0);
|
||||
for (size_t I = 0; I < Length; ++I)
|
||||
OS << '-';
|
||||
}
|
||||
|
||||
/// \brief Return the color which correponds to the coverage percentage of a
|
||||
/// certain metric.
|
||||
template <typename T>
|
||||
raw_ostream::Colors determineCoveragePercentageColor(const T &Info) {
|
||||
if (Info.isFullyCovered())
|
||||
return raw_ostream::GREEN;
|
||||
return Info.getPercentCovered() >= 80.0 ? raw_ostream::YELLOW
|
||||
: raw_ostream::RED;
|
||||
}
|
||||
|
||||
/// \brief Get the number of redundant path components in each path in \p Paths.
|
||||
unsigned getNumRedundantPathComponents(ArrayRef<std::string> Paths) {
|
||||
// To start, set the number of redundant path components to the maximum
|
||||
// possible value.
|
||||
SmallVector<StringRef, 8> FirstPathComponents{sys::path::begin(Paths[0]),
|
||||
sys::path::end(Paths[0])};
|
||||
unsigned NumRedundant = FirstPathComponents.size();
|
||||
|
||||
for (unsigned I = 1, E = Paths.size(); NumRedundant > 0 && I < E; ++I) {
|
||||
StringRef Path = Paths[I];
|
||||
for (const auto &Component :
|
||||
enumerate(make_range(sys::path::begin(Path), sys::path::end(Path)))) {
|
||||
// Do not increase the number of redundant components: that would remove
|
||||
// useful parts of already-visited paths.
|
||||
if (Component.index() >= NumRedundant)
|
||||
break;
|
||||
|
||||
// Lower the number of redundant components when there's a mismatch
|
||||
// between the first path, and the path under consideration.
|
||||
if (FirstPathComponents[Component.index()] != Component.value()) {
|
||||
NumRedundant = Component.index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NumRedundant;
|
||||
}
|
||||
|
||||
/// \brief Determine the length of the longest redundant prefix of the paths in
|
||||
/// \p Paths.
|
||||
unsigned getRedundantPrefixLen(ArrayRef<std::string> Paths) {
|
||||
// If there's at most one path, no path components are redundant.
|
||||
if (Paths.size() <= 1)
|
||||
return 0;
|
||||
|
||||
unsigned PrefixLen = 0;
|
||||
unsigned NumRedundant = getNumRedundantPathComponents(Paths);
|
||||
auto Component = sys::path::begin(Paths[0]);
|
||||
for (unsigned I = 0; I < NumRedundant; ++I) {
|
||||
auto LastComponent = Component;
|
||||
++Component;
|
||||
PrefixLen += Component - LastComponent;
|
||||
}
|
||||
return PrefixLen;
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void CoverageReport::render(const FileCoverageSummary &File,
|
||||
raw_ostream &OS) const {
|
||||
auto FileCoverageColor =
|
||||
determineCoveragePercentageColor(File.RegionCoverage);
|
||||
auto FuncCoverageColor =
|
||||
determineCoveragePercentageColor(File.FunctionCoverage);
|
||||
auto InstantiationCoverageColor =
|
||||
determineCoveragePercentageColor(File.InstantiationCoverage);
|
||||
auto LineCoverageColor = determineCoveragePercentageColor(File.LineCoverage);
|
||||
SmallString<256> FileName = File.Name;
|
||||
sys::path::remove_dots(FileName, /*remove_dot_dots=*/true);
|
||||
sys::path::native(FileName);
|
||||
OS << column(FileName, FileReportColumns[0], Column::NoTrim);
|
||||
|
||||
if (Options.ShowRegionSummary) {
|
||||
OS << format("%*u", FileReportColumns[1],
|
||||
(unsigned)File.RegionCoverage.getNumRegions());
|
||||
Options.colored_ostream(OS, FileCoverageColor)
|
||||
<< format("%*u", FileReportColumns[2],
|
||||
(unsigned)(File.RegionCoverage.getNumRegions() -
|
||||
File.RegionCoverage.getCovered()));
|
||||
if (File.RegionCoverage.getNumRegions())
|
||||
Options.colored_ostream(OS, FileCoverageColor)
|
||||
<< format("%*.2f", FileReportColumns[3] - 1,
|
||||
File.RegionCoverage.getPercentCovered())
|
||||
<< '%';
|
||||
else
|
||||
OS << column("-", FileReportColumns[3], Column::RightAlignment);
|
||||
}
|
||||
|
||||
OS << format("%*u", FileReportColumns[4],
|
||||
(unsigned)File.FunctionCoverage.getNumFunctions());
|
||||
OS << format("%*u", FileReportColumns[5],
|
||||
(unsigned)(File.FunctionCoverage.getNumFunctions() -
|
||||
File.FunctionCoverage.getExecuted()));
|
||||
if (File.FunctionCoverage.getNumFunctions())
|
||||
Options.colored_ostream(OS, FuncCoverageColor)
|
||||
<< format("%*.2f", FileReportColumns[6] - 1,
|
||||
File.FunctionCoverage.getPercentCovered())
|
||||
<< '%';
|
||||
else
|
||||
OS << column("-", FileReportColumns[6], Column::RightAlignment);
|
||||
|
||||
if (Options.ShowInstantiationSummary) {
|
||||
OS << format("%*u", FileReportColumns[7],
|
||||
(unsigned)File.InstantiationCoverage.getNumFunctions());
|
||||
OS << format("%*u", FileReportColumns[8],
|
||||
(unsigned)(File.InstantiationCoverage.getNumFunctions() -
|
||||
File.InstantiationCoverage.getExecuted()));
|
||||
if (File.InstantiationCoverage.getNumFunctions())
|
||||
Options.colored_ostream(OS, InstantiationCoverageColor)
|
||||
<< format("%*.2f", FileReportColumns[9] - 1,
|
||||
File.InstantiationCoverage.getPercentCovered())
|
||||
<< '%';
|
||||
else
|
||||
OS << column("-", FileReportColumns[9], Column::RightAlignment);
|
||||
}
|
||||
|
||||
OS << format("%*u", FileReportColumns[10],
|
||||
(unsigned)File.LineCoverage.getNumLines());
|
||||
Options.colored_ostream(OS, LineCoverageColor) << format(
|
||||
"%*u", FileReportColumns[11], (unsigned)(File.LineCoverage.getNumLines() -
|
||||
File.LineCoverage.getCovered()));
|
||||
if (File.LineCoverage.getNumLines())
|
||||
Options.colored_ostream(OS, LineCoverageColor)
|
||||
<< format("%*.2f", FileReportColumns[12] - 1,
|
||||
File.LineCoverage.getPercentCovered())
|
||||
<< '%';
|
||||
else
|
||||
OS << column("-", FileReportColumns[12], Column::RightAlignment);
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
void CoverageReport::render(const FunctionCoverageSummary &Function,
|
||||
const DemangleCache &DC,
|
||||
raw_ostream &OS) const {
|
||||
auto FuncCoverageColor =
|
||||
determineCoveragePercentageColor(Function.RegionCoverage);
|
||||
auto LineCoverageColor =
|
||||
determineCoveragePercentageColor(Function.LineCoverage);
|
||||
OS << column(DC.demangle(Function.Name), FunctionReportColumns[0],
|
||||
Column::RightTrim)
|
||||
<< format("%*u", FunctionReportColumns[1],
|
||||
(unsigned)Function.RegionCoverage.getNumRegions());
|
||||
Options.colored_ostream(OS, FuncCoverageColor)
|
||||
<< format("%*u", FunctionReportColumns[2],
|
||||
(unsigned)(Function.RegionCoverage.getNumRegions() -
|
||||
Function.RegionCoverage.getCovered()));
|
||||
Options.colored_ostream(
|
||||
OS, determineCoveragePercentageColor(Function.RegionCoverage))
|
||||
<< format("%*.2f", FunctionReportColumns[3] - 1,
|
||||
Function.RegionCoverage.getPercentCovered())
|
||||
<< '%';
|
||||
OS << format("%*u", FunctionReportColumns[4],
|
||||
(unsigned)Function.LineCoverage.getNumLines());
|
||||
Options.colored_ostream(OS, LineCoverageColor)
|
||||
<< format("%*u", FunctionReportColumns[5],
|
||||
(unsigned)(Function.LineCoverage.getNumLines() -
|
||||
Function.LineCoverage.getCovered()));
|
||||
Options.colored_ostream(
|
||||
OS, determineCoveragePercentageColor(Function.LineCoverage))
|
||||
<< format("%*.2f", FunctionReportColumns[6] - 1,
|
||||
Function.LineCoverage.getPercentCovered())
|
||||
<< '%';
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
|
||||
const DemangleCache &DC,
|
||||
raw_ostream &OS) {
|
||||
bool isFirst = true;
|
||||
for (StringRef Filename : Files) {
|
||||
auto Functions = Coverage.getCoveredFunctions(Filename);
|
||||
|
||||
if (isFirst)
|
||||
isFirst = false;
|
||||
else
|
||||
OS << "\n";
|
||||
|
||||
std::vector<StringRef> Funcnames;
|
||||
for (const auto &F : Functions)
|
||||
Funcnames.emplace_back(DC.demangle(F.Name));
|
||||
adjustColumnWidths({}, Funcnames);
|
||||
|
||||
OS << "File '" << Filename << "':\n";
|
||||
OS << column("Name", FunctionReportColumns[0])
|
||||
<< column("Regions", FunctionReportColumns[1], Column::RightAlignment)
|
||||
<< column("Miss", FunctionReportColumns[2], Column::RightAlignment)
|
||||
<< column("Cover", FunctionReportColumns[3], Column::RightAlignment)
|
||||
<< column("Lines", FunctionReportColumns[4], Column::RightAlignment)
|
||||
<< column("Miss", FunctionReportColumns[5], Column::RightAlignment)
|
||||
<< column("Cover", FunctionReportColumns[6], Column::RightAlignment);
|
||||
OS << "\n";
|
||||
renderDivider(FunctionReportColumns, OS);
|
||||
OS << "\n";
|
||||
FunctionCoverageSummary Totals("TOTAL");
|
||||
for (const auto &F : Functions) {
|
||||
auto Function = FunctionCoverageSummary::get(Coverage, F);
|
||||
++Totals.ExecutionCount;
|
||||
Totals.RegionCoverage += Function.RegionCoverage;
|
||||
Totals.LineCoverage += Function.LineCoverage;
|
||||
render(Function, DC, OS);
|
||||
}
|
||||
if (Totals.ExecutionCount) {
|
||||
renderDivider(FunctionReportColumns, OS);
|
||||
OS << "\n";
|
||||
render(Totals, DC, OS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FileCoverageSummary> CoverageReport::prepareFileReports(
|
||||
const coverage::CoverageMapping &Coverage, FileCoverageSummary &Totals,
|
||||
ArrayRef<std::string> Files, const CoverageViewOptions &Options,
|
||||
const CoverageFilter &Filters) {
|
||||
std::vector<FileCoverageSummary> FileReports;
|
||||
unsigned LCP = getRedundantPrefixLen(Files);
|
||||
|
||||
for (StringRef Filename : Files) {
|
||||
FileCoverageSummary Summary(Filename.drop_front(LCP));
|
||||
|
||||
for (const auto &Group : Coverage.getInstantiationGroups(Filename)) {
|
||||
std::vector<FunctionCoverageSummary> InstantiationSummaries;
|
||||
for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
|
||||
if (!Filters.matches(Coverage, *F))
|
||||
continue;
|
||||
auto InstantiationSummary = FunctionCoverageSummary::get(Coverage, *F);
|
||||
Summary.addInstantiation(InstantiationSummary);
|
||||
Totals.addInstantiation(InstantiationSummary);
|
||||
InstantiationSummaries.push_back(InstantiationSummary);
|
||||
}
|
||||
if (InstantiationSummaries.empty())
|
||||
continue;
|
||||
|
||||
auto GroupSummary =
|
||||
FunctionCoverageSummary::get(Group, InstantiationSummaries);
|
||||
|
||||
if (Options.Debug)
|
||||
outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
|
||||
<< "size = " << Group.size() << "\n";
|
||||
|
||||
Summary.addFunction(GroupSummary);
|
||||
Totals.addFunction(GroupSummary);
|
||||
}
|
||||
|
||||
FileReports.push_back(Summary);
|
||||
}
|
||||
|
||||
return FileReports;
|
||||
}
|
||||
|
||||
void CoverageReport::renderFileReports(raw_ostream &OS) const {
|
||||
std::vector<std::string> UniqueSourceFiles;
|
||||
for (StringRef SF : Coverage.getUniqueSourceFiles())
|
||||
UniqueSourceFiles.emplace_back(SF.str());
|
||||
renderFileReports(OS, UniqueSourceFiles);
|
||||
}
|
||||
|
||||
void CoverageReport::renderFileReports(
|
||||
raw_ostream &OS, ArrayRef<std::string> Files) const {
|
||||
renderFileReports(OS, Files, CoverageFiltersMatchAll());
|
||||
}
|
||||
|
||||
void CoverageReport::renderFileReports(
|
||||
raw_ostream &OS, ArrayRef<std::string> Files,
|
||||
const CoverageFiltersMatchAll &Filters) const {
|
||||
FileCoverageSummary Totals("TOTAL");
|
||||
auto FileReports =
|
||||
prepareFileReports(Coverage, Totals, Files, Options, Filters);
|
||||
|
||||
std::vector<StringRef> Filenames;
|
||||
for (const FileCoverageSummary &FCS : FileReports)
|
||||
Filenames.emplace_back(FCS.Name);
|
||||
adjustColumnWidths(Filenames, {});
|
||||
|
||||
OS << column("Filename", FileReportColumns[0]);
|
||||
if (Options.ShowRegionSummary)
|
||||
OS << column("Regions", FileReportColumns[1], Column::RightAlignment)
|
||||
<< column("Missed Regions", FileReportColumns[2], Column::RightAlignment)
|
||||
<< column("Cover", FileReportColumns[3], Column::RightAlignment);
|
||||
OS << column("Functions", FileReportColumns[4], Column::RightAlignment)
|
||||
<< column("Missed Functions", FileReportColumns[5], Column::RightAlignment)
|
||||
<< column("Executed", FileReportColumns[6], Column::RightAlignment);
|
||||
if (Options.ShowInstantiationSummary)
|
||||
OS << column("Instantiations", FileReportColumns[7], Column::RightAlignment)
|
||||
<< column("Missed Insts.", FileReportColumns[8], Column::RightAlignment)
|
||||
<< column("Executed", FileReportColumns[9], Column::RightAlignment);
|
||||
OS << column("Lines", FileReportColumns[10], Column::RightAlignment)
|
||||
<< column("Missed Lines", FileReportColumns[11], Column::RightAlignment)
|
||||
<< column("Cover", FileReportColumns[12], Column::RightAlignment) << "\n";
|
||||
renderDivider(FileReportColumns, OS);
|
||||
OS << "\n";
|
||||
|
||||
bool EmptyFiles = false;
|
||||
for (const FileCoverageSummary &FCS : FileReports) {
|
||||
if (FCS.FunctionCoverage.getNumFunctions())
|
||||
render(FCS, OS);
|
||||
else
|
||||
EmptyFiles = true;
|
||||
}
|
||||
|
||||
if (EmptyFiles && Filters.empty()) {
|
||||
OS << "\n"
|
||||
<< "Files which contain no functions:\n";
|
||||
|
||||
for (const FileCoverageSummary &FCS : FileReports)
|
||||
if (!FCS.FunctionCoverage.getNumFunctions())
|
||||
render(FCS, OS);
|
||||
}
|
||||
|
||||
renderDivider(FileReportColumns, OS);
|
||||
OS << "\n";
|
||||
render(Totals, OS);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
61
external/llvm/tools/llvm-cov/CoverageReport.h
vendored
61
external/llvm/tools/llvm-cov/CoverageReport.h
vendored
@ -1,61 +0,0 @@
|
||||
//===- CoverageReport.h - Code coverage report ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class implements rendering of a code coverage report.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_COVERAGEREPORT_H
|
||||
#define LLVM_COV_COVERAGEREPORT_H
|
||||
|
||||
#include "CoverageFilters.h"
|
||||
#include "CoverageSummaryInfo.h"
|
||||
#include "CoverageViewOptions.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Displays the code coverage report.
|
||||
class CoverageReport {
|
||||
const CoverageViewOptions &Options;
|
||||
const coverage::CoverageMapping &Coverage;
|
||||
|
||||
void render(const FileCoverageSummary &File, raw_ostream &OS) const;
|
||||
void render(const FunctionCoverageSummary &Function, const DemangleCache &DC,
|
||||
raw_ostream &OS) const;
|
||||
|
||||
public:
|
||||
CoverageReport(const CoverageViewOptions &Options,
|
||||
const coverage::CoverageMapping &Coverage)
|
||||
: Options(Options), Coverage(Coverage) {}
|
||||
|
||||
void renderFunctionReports(ArrayRef<std::string> Files,
|
||||
const DemangleCache &DC, raw_ostream &OS);
|
||||
|
||||
/// Prepare file reports for the files specified in \p Files.
|
||||
static std::vector<FileCoverageSummary>
|
||||
prepareFileReports(const coverage::CoverageMapping &Coverage,
|
||||
FileCoverageSummary &Totals, ArrayRef<std::string> Files,
|
||||
const CoverageViewOptions &Options,
|
||||
const CoverageFilter &Filters = CoverageFiltersMatchAll());
|
||||
|
||||
/// Render file reports for every unique file in the coverage mapping.
|
||||
void renderFileReports(raw_ostream &OS) const;
|
||||
|
||||
/// Render file reports for the files specified in \p Files.
|
||||
void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files) const;
|
||||
|
||||
/// Render file reports for the files specified in \p Files and the functions
|
||||
/// in \p Filters.
|
||||
void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files,
|
||||
const CoverageFiltersMatchAll &Filters) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_COV_COVERAGEREPORT_H
|
@ -1,71 +0,0 @@
|
||||
//===- CoverageSummaryInfo.cpp - Coverage summary for function/file -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// These structures are used to represent code coverage metrics
|
||||
// for functions/files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoverageSummaryInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace coverage;
|
||||
|
||||
FunctionCoverageSummary
|
||||
FunctionCoverageSummary::get(const CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function) {
|
||||
// Compute the region coverage.
|
||||
size_t NumCodeRegions = 0, CoveredRegions = 0;
|
||||
for (auto &CR : Function.CountedRegions) {
|
||||
if (CR.Kind != CounterMappingRegion::CodeRegion)
|
||||
continue;
|
||||
++NumCodeRegions;
|
||||
if (CR.ExecutionCount != 0)
|
||||
++CoveredRegions;
|
||||
}
|
||||
|
||||
// Compute the line coverage
|
||||
size_t NumLines = 0, CoveredLines = 0;
|
||||
CoverageData CD = CM.getCoverageForFunction(Function);
|
||||
for (const auto &LCS : getLineCoverageStats(CD)) {
|
||||
if (!LCS.isMapped())
|
||||
continue;
|
||||
++NumLines;
|
||||
if (LCS.getExecutionCount())
|
||||
++CoveredLines;
|
||||
}
|
||||
|
||||
return FunctionCoverageSummary(
|
||||
Function.Name, Function.ExecutionCount,
|
||||
RegionCoverageInfo(CoveredRegions, NumCodeRegions),
|
||||
LineCoverageInfo(CoveredLines, NumLines));
|
||||
}
|
||||
|
||||
FunctionCoverageSummary
|
||||
FunctionCoverageSummary::get(const InstantiationGroup &Group,
|
||||
ArrayRef<FunctionCoverageSummary> Summaries) {
|
||||
std::string Name;
|
||||
if (Group.hasName()) {
|
||||
Name = Group.getName();
|
||||
} else {
|
||||
llvm::raw_string_ostream OS(Name);
|
||||
OS << "Definition at line " << Group.getLine() << ", column "
|
||||
<< Group.getColumn();
|
||||
}
|
||||
|
||||
FunctionCoverageSummary Summary(Name);
|
||||
Summary.ExecutionCount = Group.getTotalExecutionCount();
|
||||
Summary.RegionCoverage = Summaries[0].RegionCoverage;
|
||||
Summary.LineCoverage = Summaries[0].LineCoverage;
|
||||
for (const auto &FCS : Summaries.drop_front()) {
|
||||
Summary.RegionCoverage.merge(FCS.RegionCoverage);
|
||||
Summary.LineCoverage.merge(FCS.LineCoverage);
|
||||
}
|
||||
return Summary;
|
||||
}
|
205
external/llvm/tools/llvm-cov/CoverageSummaryInfo.h
vendored
205
external/llvm/tools/llvm-cov/CoverageSummaryInfo.h
vendored
@ -1,205 +0,0 @@
|
||||
//===- CoverageSummaryInfo.h - Coverage summary for function/file ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// These structures are used to represent code coverage metrics
|
||||
// for functions/files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_COVERAGESUMMARYINFO_H
|
||||
#define LLVM_COV_COVERAGESUMMARYINFO_H
|
||||
|
||||
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Provides information about region coverage for a function/file.
|
||||
class RegionCoverageInfo {
|
||||
/// \brief The number of regions that were executed at least once.
|
||||
size_t Covered;
|
||||
|
||||
/// \brief The total number of regions in a function/file.
|
||||
size_t NumRegions;
|
||||
|
||||
public:
|
||||
RegionCoverageInfo() : Covered(0), NumRegions(0) {}
|
||||
|
||||
RegionCoverageInfo(size_t Covered, size_t NumRegions)
|
||||
: Covered(Covered), NumRegions(NumRegions) {
|
||||
assert(Covered <= NumRegions && "Covered regions over-counted");
|
||||
}
|
||||
|
||||
RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) {
|
||||
Covered += RHS.Covered;
|
||||
NumRegions += RHS.NumRegions;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void merge(const RegionCoverageInfo &RHS) {
|
||||
Covered = std::max(Covered, RHS.Covered);
|
||||
NumRegions = std::max(NumRegions, RHS.NumRegions);
|
||||
}
|
||||
|
||||
size_t getCovered() const { return Covered; }
|
||||
|
||||
size_t getNumRegions() const { return NumRegions; }
|
||||
|
||||
bool isFullyCovered() const { return Covered == NumRegions; }
|
||||
|
||||
double getPercentCovered() const {
|
||||
assert(Covered <= NumRegions && "Covered regions over-counted");
|
||||
if (NumRegions == 0)
|
||||
return 0.0;
|
||||
return double(Covered) / double(NumRegions) * 100.0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Provides information about line coverage for a function/file.
|
||||
class LineCoverageInfo {
|
||||
/// \brief The number of lines that were executed at least once.
|
||||
size_t Covered;
|
||||
|
||||
/// \brief The total number of lines in a function/file.
|
||||
size_t NumLines;
|
||||
|
||||
public:
|
||||
LineCoverageInfo() : Covered(0), NumLines(0) {}
|
||||
|
||||
LineCoverageInfo(size_t Covered, size_t NumLines)
|
||||
: Covered(Covered), NumLines(NumLines) {
|
||||
assert(Covered <= NumLines && "Covered lines over-counted");
|
||||
}
|
||||
|
||||
LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) {
|
||||
Covered += RHS.Covered;
|
||||
NumLines += RHS.NumLines;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void merge(const LineCoverageInfo &RHS) {
|
||||
Covered = std::max(Covered, RHS.Covered);
|
||||
NumLines = std::max(NumLines, RHS.NumLines);
|
||||
}
|
||||
|
||||
size_t getCovered() const { return Covered; }
|
||||
|
||||
size_t getNumLines() const { return NumLines; }
|
||||
|
||||
bool isFullyCovered() const { return Covered == NumLines; }
|
||||
|
||||
double getPercentCovered() const {
|
||||
assert(Covered <= NumLines && "Covered lines over-counted");
|
||||
if (NumLines == 0)
|
||||
return 0.0;
|
||||
return double(Covered) / double(NumLines) * 100.0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Provides information about function coverage for a file.
|
||||
class FunctionCoverageInfo {
|
||||
/// \brief The number of functions that were executed.
|
||||
size_t Executed;
|
||||
|
||||
/// \brief The total number of functions in this file.
|
||||
size_t NumFunctions;
|
||||
|
||||
public:
|
||||
FunctionCoverageInfo() : Executed(0), NumFunctions(0) {}
|
||||
|
||||
FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
|
||||
: Executed(Executed), NumFunctions(NumFunctions) {}
|
||||
|
||||
void addFunction(bool Covered) {
|
||||
if (Covered)
|
||||
++Executed;
|
||||
++NumFunctions;
|
||||
}
|
||||
|
||||
size_t getExecuted() const { return Executed; }
|
||||
|
||||
size_t getNumFunctions() const { return NumFunctions; }
|
||||
|
||||
bool isFullyCovered() const { return Executed == NumFunctions; }
|
||||
|
||||
double getPercentCovered() const {
|
||||
assert(Executed <= NumFunctions && "Covered functions over-counted");
|
||||
if (NumFunctions == 0)
|
||||
return 0.0;
|
||||
return double(Executed) / double(NumFunctions) * 100.0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A summary of function's code coverage.
|
||||
struct FunctionCoverageSummary {
|
||||
std::string Name;
|
||||
uint64_t ExecutionCount;
|
||||
RegionCoverageInfo RegionCoverage;
|
||||
LineCoverageInfo LineCoverage;
|
||||
|
||||
FunctionCoverageSummary(const std::string &Name)
|
||||
: Name(Name), ExecutionCount(0), RegionCoverage(), LineCoverage() {}
|
||||
|
||||
FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
|
||||
const RegionCoverageInfo &RegionCoverage,
|
||||
const LineCoverageInfo &LineCoverage)
|
||||
: Name(Name), ExecutionCount(ExecutionCount),
|
||||
RegionCoverage(RegionCoverage), LineCoverage(LineCoverage) {}
|
||||
|
||||
/// \brief Compute the code coverage summary for the given function coverage
|
||||
/// mapping record.
|
||||
static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
|
||||
const coverage::FunctionRecord &Function);
|
||||
|
||||
/// Compute the code coverage summary for an instantiation group \p Group,
|
||||
/// given a list of summaries for each instantiation in \p Summaries.
|
||||
static FunctionCoverageSummary
|
||||
get(const coverage::InstantiationGroup &Group,
|
||||
ArrayRef<FunctionCoverageSummary> Summaries);
|
||||
};
|
||||
|
||||
/// \brief A summary of file's code coverage.
|
||||
struct FileCoverageSummary {
|
||||
StringRef Name;
|
||||
RegionCoverageInfo RegionCoverage;
|
||||
LineCoverageInfo LineCoverage;
|
||||
FunctionCoverageInfo FunctionCoverage;
|
||||
FunctionCoverageInfo InstantiationCoverage;
|
||||
|
||||
FileCoverageSummary(StringRef Name)
|
||||
: Name(Name), RegionCoverage(), LineCoverage(), FunctionCoverage(),
|
||||
InstantiationCoverage() {}
|
||||
|
||||
void addFunction(const FunctionCoverageSummary &Function) {
|
||||
RegionCoverage += Function.RegionCoverage;
|
||||
LineCoverage += Function.LineCoverage;
|
||||
FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
|
||||
}
|
||||
|
||||
void addInstantiation(const FunctionCoverageSummary &Function) {
|
||||
InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A cache for demangled symbols.
|
||||
struct DemangleCache {
|
||||
StringMap<std::string> DemangledNames;
|
||||
|
||||
/// \brief Demangle \p Sym if possible. Otherwise, just return \p Sym.
|
||||
StringRef demangle(StringRef Sym) const {
|
||||
const auto DemangledName = DemangledNames.find(Sym);
|
||||
if (DemangledName == DemangledNames.end())
|
||||
return Sym;
|
||||
return DemangledName->getValue();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_COV_COVERAGESUMMARYINFO_H
|
@ -1,70 +0,0 @@
|
||||
//===- CoverageViewOptions.h - Code coverage display options -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_COVERAGEVIEWOPTIONS_H
|
||||
#define LLVM_COV_COVERAGEVIEWOPTIONS_H
|
||||
|
||||
#include "RenderingSupport.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief The options for displaying the code coverage information.
|
||||
struct CoverageViewOptions {
|
||||
enum class OutputFormat {
|
||||
Text,
|
||||
HTML
|
||||
};
|
||||
|
||||
bool Debug;
|
||||
bool Colors;
|
||||
bool ShowLineNumbers;
|
||||
bool ShowLineStats;
|
||||
bool ShowRegionMarkers;
|
||||
bool ShowExpandedRegions;
|
||||
bool ShowFunctionInstantiations;
|
||||
bool ShowFullFilenames;
|
||||
bool ShowRegionSummary;
|
||||
bool ShowInstantiationSummary;
|
||||
bool ExportSummaryOnly;
|
||||
OutputFormat Format;
|
||||
std::string ShowOutputDirectory;
|
||||
std::vector<std::string> DemanglerOpts;
|
||||
uint32_t TabSize;
|
||||
std::string ProjectTitle;
|
||||
std::string CreatedTimeStr;
|
||||
|
||||
/// \brief Change the output's stream color if the colors are enabled.
|
||||
ColoredRawOstream colored_ostream(raw_ostream &OS,
|
||||
raw_ostream::Colors Color) const {
|
||||
return llvm::colored_ostream(OS, Color, Colors);
|
||||
}
|
||||
|
||||
/// \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(); }
|
||||
|
||||
/// \brief Check if a project title has been specified.
|
||||
bool hasProjectTitle() const { return !ProjectTitle.empty(); }
|
||||
|
||||
/// \brief Check if the created time of the profile data file is available.
|
||||
bool hasCreatedTime() const { return !CreatedTimeStr.empty(); }
|
||||
|
||||
/// \brief Get the LLVM version string.
|
||||
std::string getLLVMVersionString() const {
|
||||
std::string VersionString = "Generated by llvm-cov -- llvm version ";
|
||||
VersionString += LLVM_VERSION_STRING;
|
||||
return VersionString;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LLVM_COV_COVERAGEVIEWOPTIONS_H
|
22
external/llvm/tools/llvm-cov/LLVMBuild.txt
vendored
22
external/llvm/tools/llvm-cov/LLVMBuild.txt
vendored
@ -1,22 +0,0 @@
|
||||
;===- ./tools/llvm-cov/LLVMBuild.txt ---------------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Tool
|
||||
name = llvm-cov
|
||||
parent = Tools
|
||||
required_libraries = Coverage Support Instrumentation
|
61
external/llvm/tools/llvm-cov/RenderingSupport.h
vendored
61
external/llvm/tools/llvm-cov/RenderingSupport.h
vendored
@ -1,61 +0,0 @@
|
||||
//===- RenderingSupport.h - output stream rendering support functions ----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_RENDERINGSUPPORT_H
|
||||
#define LLVM_COV_RENDERINGSUPPORT_H
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief A helper class that resets the output stream's color if needed
|
||||
/// when destroyed.
|
||||
class ColoredRawOstream {
|
||||
ColoredRawOstream(const ColoredRawOstream &OS) = delete;
|
||||
|
||||
public:
|
||||
raw_ostream &OS;
|
||||
bool IsColorUsed;
|
||||
|
||||
ColoredRawOstream(raw_ostream &OS, bool IsColorUsed)
|
||||
: OS(OS), IsColorUsed(IsColorUsed) {}
|
||||
|
||||
ColoredRawOstream(ColoredRawOstream &&Other)
|
||||
: OS(Other.OS), IsColorUsed(Other.IsColorUsed) {
|
||||
// Reset the other IsColorUsed so that the other object won't reset the
|
||||
// color when destroyed.
|
||||
Other.IsColorUsed = false;
|
||||
}
|
||||
|
||||
~ColoredRawOstream() {
|
||||
if (IsColorUsed)
|
||||
OS.resetColor();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline raw_ostream &operator<<(const ColoredRawOstream &OS, T &&Value) {
|
||||
return OS.OS << std::forward<T>(Value);
|
||||
}
|
||||
|
||||
/// \brief Change the color of the output stream if the `IsColorUsed` flag
|
||||
/// is true. Returns an object that resets the color when destroyed.
|
||||
inline ColoredRawOstream colored_ostream(raw_ostream &OS,
|
||||
raw_ostream::Colors Color,
|
||||
bool IsColorUsed = true,
|
||||
bool Bold = false, bool BG = false) {
|
||||
if (IsColorUsed)
|
||||
OS.changeColor(Color, Bold, BG);
|
||||
return ColoredRawOstream(OS, IsColorUsed);
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_COV_RENDERINGSUPPORT_H
|
258
external/llvm/tools/llvm-cov/SourceCoverageView.cpp
vendored
258
external/llvm/tools/llvm-cov/SourceCoverageView.cpp
vendored
@ -1,258 +0,0 @@
|
||||
//===- SourceCoverageView.cpp - Code coverage view for source code --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file This class implements rendering for code coverage of source code.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SourceCoverageView.h"
|
||||
#include "SourceCoverageViewHTML.h"
|
||||
#include "SourceCoverageViewText.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/LineIterator.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void CoveragePrinter::StreamDestructor::operator()(raw_ostream *OS) const {
|
||||
if (OS == &outs())
|
||||
return;
|
||||
delete OS;
|
||||
}
|
||||
|
||||
std::string CoveragePrinter::getOutputPath(StringRef Path, StringRef Extension,
|
||||
bool InToplevel,
|
||||
bool Relative) const {
|
||||
assert(Extension.size() && "The file extension may not be empty");
|
||||
|
||||
SmallString<256> FullPath;
|
||||
|
||||
if (!Relative)
|
||||
FullPath.append(Opts.ShowOutputDirectory);
|
||||
|
||||
if (!InToplevel)
|
||||
sys::path::append(FullPath, getCoverageDir());
|
||||
|
||||
SmallString<256> ParentPath = sys::path::parent_path(Path);
|
||||
sys::path::remove_dots(ParentPath, /*remove_dot_dots=*/true);
|
||||
sys::path::append(FullPath, sys::path::relative_path(ParentPath));
|
||||
|
||||
auto PathFilename = (sys::path::filename(Path) + "." + Extension).str();
|
||||
sys::path::append(FullPath, PathFilename);
|
||||
sys::path::native(FullPath);
|
||||
|
||||
return FullPath.str();
|
||||
}
|
||||
|
||||
Expected<CoveragePrinter::OwnedStream>
|
||||
CoveragePrinter::createOutputStream(StringRef Path, StringRef Extension,
|
||||
bool InToplevel) const {
|
||||
if (!Opts.hasOutputDirectory())
|
||||
return OwnedStream(&outs());
|
||||
|
||||
std::string FullPath = getOutputPath(Path, Extension, InToplevel, false);
|
||||
|
||||
auto ParentDir = sys::path::parent_path(FullPath);
|
||||
if (auto E = sys::fs::create_directories(ParentDir))
|
||||
return errorCodeToError(E);
|
||||
|
||||
std::error_code E;
|
||||
raw_ostream *RawStream = new raw_fd_ostream(FullPath, E, sys::fs::F_RW);
|
||||
auto OS = CoveragePrinter::OwnedStream(RawStream);
|
||||
if (E)
|
||||
return errorCodeToError(E);
|
||||
return std::move(OS);
|
||||
}
|
||||
|
||||
std::unique_ptr<CoveragePrinter>
|
||||
CoveragePrinter::create(const CoverageViewOptions &Opts) {
|
||||
switch (Opts.Format) {
|
||||
case CoverageViewOptions::OutputFormat::Text:
|
||||
return llvm::make_unique<CoveragePrinterText>(Opts);
|
||||
case CoverageViewOptions::OutputFormat::HTML:
|
||||
return llvm::make_unique<CoveragePrinterHTML>(Opts);
|
||||
}
|
||||
llvm_unreachable("Unknown coverage output format!");
|
||||
}
|
||||
|
||||
unsigned SourceCoverageView::getFirstUncoveredLineNo() {
|
||||
const auto MinSegIt = find_if(CoverageInfo, [](const CoverageSegment &S) {
|
||||
return S.HasCount && S.Count == 0;
|
||||
});
|
||||
|
||||
// There is no uncovered line, return zero.
|
||||
if (MinSegIt == CoverageInfo.end())
|
||||
return 0;
|
||||
|
||||
return (*MinSegIt).Line;
|
||||
}
|
||||
|
||||
std::string SourceCoverageView::formatCount(uint64_t N) {
|
||||
std::string Number = utostr(N);
|
||||
int Len = Number.size();
|
||||
if (Len <= 3)
|
||||
return Number;
|
||||
int IntLen = Len % 3 == 0 ? 3 : Len % 3;
|
||||
std::string Result(Number.data(), IntLen);
|
||||
if (IntLen != 3) {
|
||||
Result.push_back('.');
|
||||
Result += Number.substr(IntLen, 3 - IntLen);
|
||||
}
|
||||
Result.push_back(" kMGTPEZY"[(Len - 1) / 3]);
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool SourceCoverageView::shouldRenderRegionMarkers(
|
||||
const LineCoverageStats &LCS) const {
|
||||
if (!getOptions().ShowRegionMarkers)
|
||||
return false;
|
||||
|
||||
CoverageSegmentArray Segments = LCS.getLineSegments();
|
||||
if (Segments.empty())
|
||||
return false;
|
||||
for (unsigned I = 0, E = Segments.size() - 1; I < E; ++I) {
|
||||
const auto *CurSeg = Segments[I];
|
||||
if (!CurSeg->IsRegionEntry || CurSeg->Count == LCS.getExecutionCount())
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SourceCoverageView::hasSubViews() const {
|
||||
return !ExpansionSubViews.empty() || !InstantiationSubViews.empty();
|
||||
}
|
||||
|
||||
std::unique_ptr<SourceCoverageView>
|
||||
SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File,
|
||||
const CoverageViewOptions &Options,
|
||||
CoverageData &&CoverageInfo) {
|
||||
switch (Options.Format) {
|
||||
case CoverageViewOptions::OutputFormat::Text:
|
||||
return llvm::make_unique<SourceCoverageViewText>(
|
||||
SourceName, File, Options, std::move(CoverageInfo));
|
||||
case CoverageViewOptions::OutputFormat::HTML:
|
||||
return llvm::make_unique<SourceCoverageViewHTML>(
|
||||
SourceName, File, Options, std::move(CoverageInfo));
|
||||
}
|
||||
llvm_unreachable("Unknown coverage output format!");
|
||||
}
|
||||
|
||||
std::string SourceCoverageView::getSourceName() const {
|
||||
SmallString<128> SourceText(SourceName);
|
||||
sys::path::remove_dots(SourceText, /*remove_dot_dots=*/true);
|
||||
sys::path::native(SourceText);
|
||||
return SourceText.str();
|
||||
}
|
||||
|
||||
void SourceCoverageView::addExpansion(
|
||||
const CounterMappingRegion &Region,
|
||||
std::unique_ptr<SourceCoverageView> View) {
|
||||
ExpansionSubViews.emplace_back(Region, std::move(View));
|
||||
}
|
||||
|
||||
void SourceCoverageView::addInstantiation(
|
||||
StringRef FunctionName, unsigned Line,
|
||||
std::unique_ptr<SourceCoverageView> View) {
|
||||
InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
|
||||
}
|
||||
|
||||
void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
|
||||
bool ShowSourceName, bool ShowTitle,
|
||||
unsigned ViewDepth) {
|
||||
if (ShowTitle)
|
||||
renderTitle(OS, "Coverage Report");
|
||||
|
||||
renderViewHeader(OS);
|
||||
|
||||
if (ShowSourceName)
|
||||
renderSourceName(OS, WholeFile);
|
||||
|
||||
renderTableHeader(OS, (ViewDepth > 0) ? 0 : getFirstUncoveredLineNo(),
|
||||
ViewDepth);
|
||||
|
||||
// We need the expansions and instantiations sorted so we can go through them
|
||||
// while we iterate lines.
|
||||
std::stable_sort(ExpansionSubViews.begin(), ExpansionSubViews.end());
|
||||
std::stable_sort(InstantiationSubViews.begin(), InstantiationSubViews.end());
|
||||
auto NextESV = ExpansionSubViews.begin();
|
||||
auto EndESV = ExpansionSubViews.end();
|
||||
auto NextISV = InstantiationSubViews.begin();
|
||||
auto EndISV = InstantiationSubViews.end();
|
||||
|
||||
// Get the coverage information for the file.
|
||||
auto StartSegment = CoverageInfo.begin();
|
||||
auto EndSegment = CoverageInfo.end();
|
||||
LineCoverageIterator LCI{CoverageInfo, 1};
|
||||
LineCoverageIterator LCIEnd = LCI.getEnd();
|
||||
|
||||
unsigned FirstLine = StartSegment != EndSegment ? StartSegment->Line : 0;
|
||||
for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof();
|
||||
++LI, ++LCI) {
|
||||
// If we aren't rendering the whole file, we need to filter out the prologue
|
||||
// and epilogue.
|
||||
if (!WholeFile) {
|
||||
if (LCI == LCIEnd)
|
||||
break;
|
||||
else if (LI.line_number() < FirstLine)
|
||||
continue;
|
||||
}
|
||||
|
||||
renderLinePrefix(OS, ViewDepth);
|
||||
if (getOptions().ShowLineNumbers)
|
||||
renderLineNumberColumn(OS, LI.line_number());
|
||||
|
||||
if (getOptions().ShowLineStats)
|
||||
renderLineCoverageColumn(OS, *LCI);
|
||||
|
||||
// If there are expansion subviews, we want to highlight the first one.
|
||||
unsigned ExpansionColumn = 0;
|
||||
if (NextESV != EndESV && NextESV->getLine() == LI.line_number() &&
|
||||
getOptions().Colors)
|
||||
ExpansionColumn = NextESV->getStartCol();
|
||||
|
||||
// Display the source code for the current line.
|
||||
renderLine(OS, {*LI, LI.line_number()}, *LCI, ExpansionColumn, ViewDepth);
|
||||
|
||||
// Show the region markers.
|
||||
if (shouldRenderRegionMarkers(*LCI))
|
||||
renderRegionMarkers(OS, *LCI, ViewDepth);
|
||||
|
||||
// Show the expansions and instantiations for this line.
|
||||
bool RenderedSubView = false;
|
||||
for (; NextESV != EndESV && NextESV->getLine() == LI.line_number();
|
||||
++NextESV) {
|
||||
renderViewDivider(OS, ViewDepth + 1);
|
||||
|
||||
// Re-render the current line and highlight the expansion range for
|
||||
// this subview.
|
||||
if (RenderedSubView) {
|
||||
ExpansionColumn = NextESV->getStartCol();
|
||||
renderExpansionSite(OS, {*LI, LI.line_number()}, *LCI, ExpansionColumn,
|
||||
ViewDepth);
|
||||
renderViewDivider(OS, ViewDepth + 1);
|
||||
}
|
||||
|
||||
renderExpansionView(OS, *NextESV, ViewDepth + 1);
|
||||
RenderedSubView = true;
|
||||
}
|
||||
for (; NextISV != EndISV && NextISV->Line == LI.line_number(); ++NextISV) {
|
||||
renderViewDivider(OS, ViewDepth + 1);
|
||||
renderInstantiationView(OS, *NextISV, ViewDepth + 1);
|
||||
RenderedSubView = true;
|
||||
}
|
||||
if (RenderedSubView)
|
||||
renderViewDivider(OS, ViewDepth + 1);
|
||||
renderLineSuffix(OS, ViewDepth);
|
||||
}
|
||||
|
||||
renderViewFooter(OS);
|
||||
}
|
267
external/llvm/tools/llvm-cov/SourceCoverageView.h
vendored
267
external/llvm/tools/llvm-cov/SourceCoverageView.h
vendored
@ -1,267 +0,0 @@
|
||||
//===- SourceCoverageView.h - Code coverage view for source code ----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file This class implements rendering for code coverage of source code.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
|
||||
#define LLVM_COV_SOURCECOVERAGEVIEW_H
|
||||
|
||||
#include "CoverageViewOptions.h"
|
||||
#include "CoverageSummaryInfo.h"
|
||||
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
using namespace coverage;
|
||||
|
||||
class CoverageFiltersMatchAll;
|
||||
class SourceCoverageView;
|
||||
|
||||
/// \brief A view that represents a macro or include expansion.
|
||||
struct ExpansionView {
|
||||
CounterMappingRegion Region;
|
||||
std::unique_ptr<SourceCoverageView> View;
|
||||
|
||||
ExpansionView(const CounterMappingRegion &Region,
|
||||
std::unique_ptr<SourceCoverageView> View)
|
||||
: Region(Region), View(std::move(View)) {}
|
||||
ExpansionView(ExpansionView &&RHS)
|
||||
: Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
|
||||
ExpansionView &operator=(ExpansionView &&RHS) {
|
||||
Region = std::move(RHS.Region);
|
||||
View = std::move(RHS.View);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned getLine() const { return Region.LineStart; }
|
||||
unsigned getStartCol() const { return Region.ColumnStart; }
|
||||
unsigned getEndCol() const { return Region.ColumnEnd; }
|
||||
|
||||
friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
|
||||
return LHS.Region.startLoc() < RHS.Region.startLoc();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A view that represents a function instantiation.
|
||||
struct InstantiationView {
|
||||
StringRef FunctionName;
|
||||
unsigned Line;
|
||||
std::unique_ptr<SourceCoverageView> View;
|
||||
|
||||
InstantiationView(StringRef FunctionName, unsigned Line,
|
||||
std::unique_ptr<SourceCoverageView> View)
|
||||
: FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
|
||||
|
||||
friend bool operator<(const InstantiationView &LHS,
|
||||
const InstantiationView &RHS) {
|
||||
return LHS.Line < RHS.Line;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A file manager that handles format-aware file creation.
|
||||
class CoveragePrinter {
|
||||
public:
|
||||
struct StreamDestructor {
|
||||
void operator()(raw_ostream *OS) const;
|
||||
};
|
||||
|
||||
using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
|
||||
|
||||
protected:
|
||||
const CoverageViewOptions &Opts;
|
||||
|
||||
CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
|
||||
|
||||
/// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
|
||||
/// false, skip the ToplevelDir component. If \p Relative is false, skip the
|
||||
/// OutputDir component.
|
||||
std::string getOutputPath(StringRef Path, StringRef Extension,
|
||||
bool InToplevel, bool Relative = true) const;
|
||||
|
||||
/// \brief If directory output is enabled, create a file in that directory
|
||||
/// at the path given by getOutputPath(). Otherwise, return stdout.
|
||||
Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
|
||||
bool InToplevel) const;
|
||||
|
||||
/// \brief Return the sub-directory name for file coverage reports.
|
||||
static StringRef getCoverageDir() { return "coverage"; }
|
||||
|
||||
public:
|
||||
static std::unique_ptr<CoveragePrinter>
|
||||
create(const CoverageViewOptions &Opts);
|
||||
|
||||
virtual ~CoveragePrinter() {}
|
||||
|
||||
/// @name File Creation Interface
|
||||
/// @{
|
||||
|
||||
/// \brief Create a file to print a coverage view into.
|
||||
virtual Expected<OwnedStream> createViewFile(StringRef Path,
|
||||
bool InToplevel) = 0;
|
||||
|
||||
/// \brief Close a file which has been used to print a coverage view.
|
||||
virtual void closeViewFile(OwnedStream OS) = 0;
|
||||
|
||||
/// \brief Create an index which lists reports for the given source files.
|
||||
virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
|
||||
const CoverageMapping &Coverage,
|
||||
const CoverageFiltersMatchAll &Filters) = 0;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// \brief A code coverage view of a source file or function.
|
||||
///
|
||||
/// A source coverage view and its nested sub-views form a file-oriented
|
||||
/// representation of code coverage data. This view can be printed out by a
|
||||
/// renderer which implements the Rendering Interface.
|
||||
class SourceCoverageView {
|
||||
/// A function or file name.
|
||||
StringRef SourceName;
|
||||
|
||||
/// A memory buffer backing the source on display.
|
||||
const MemoryBuffer &File;
|
||||
|
||||
/// Various options to guide the coverage renderer.
|
||||
const CoverageViewOptions &Options;
|
||||
|
||||
/// Complete coverage information about the source on display.
|
||||
CoverageData CoverageInfo;
|
||||
|
||||
/// A container for all expansions (e.g macros) in the source on display.
|
||||
std::vector<ExpansionView> ExpansionSubViews;
|
||||
|
||||
/// A container for all instantiations (e.g template functions) in the source
|
||||
/// on display.
|
||||
std::vector<InstantiationView> InstantiationSubViews;
|
||||
|
||||
/// Get the first uncovered line number for the source file.
|
||||
unsigned getFirstUncoveredLineNo();
|
||||
|
||||
protected:
|
||||
struct LineRef {
|
||||
StringRef Line;
|
||||
int64_t LineNo;
|
||||
|
||||
LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
|
||||
};
|
||||
|
||||
using CoverageSegmentArray = ArrayRef<const CoverageSegment *>;
|
||||
|
||||
/// @name Rendering Interface
|
||||
/// @{
|
||||
|
||||
/// \brief Render a header for the view.
|
||||
virtual void renderViewHeader(raw_ostream &OS) = 0;
|
||||
|
||||
/// \brief Render a footer for the view.
|
||||
virtual void renderViewFooter(raw_ostream &OS) = 0;
|
||||
|
||||
/// \brief Render the source name for the view.
|
||||
virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
|
||||
|
||||
/// \brief Render the line prefix at the given \p ViewDepth.
|
||||
virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render the line suffix at the given \p ViewDepth.
|
||||
virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render a view divider at the given \p ViewDepth.
|
||||
virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render a source line with highlighting.
|
||||
virtual void renderLine(raw_ostream &OS, LineRef L,
|
||||
const LineCoverageStats &LCS, unsigned ExpansionCol,
|
||||
unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render the line's execution count column.
|
||||
virtual void renderLineCoverageColumn(raw_ostream &OS,
|
||||
const LineCoverageStats &Line) = 0;
|
||||
|
||||
/// \brief Render the line number column.
|
||||
virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
|
||||
|
||||
/// \brief Render all the region's execution counts on a line.
|
||||
virtual void renderRegionMarkers(raw_ostream &OS,
|
||||
const LineCoverageStats &Line,
|
||||
unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render the site of an expansion.
|
||||
virtual void renderExpansionSite(raw_ostream &OS, LineRef L,
|
||||
const LineCoverageStats &LCS,
|
||||
unsigned ExpansionCol,
|
||||
unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render an expansion view and any nested views.
|
||||
virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
|
||||
unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render an instantiation view and any nested views.
|
||||
virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
|
||||
unsigned ViewDepth) = 0;
|
||||
|
||||
/// \brief Render \p Title, a project title if one is available, and the
|
||||
/// created time.
|
||||
virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
|
||||
|
||||
/// \brief Render the table header for a given source file.
|
||||
virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
|
||||
unsigned IndentLevel) = 0;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \brief Format a count using engineering notation with 3 significant
|
||||
/// digits.
|
||||
static std::string formatCount(uint64_t N);
|
||||
|
||||
/// \brief Check if region marker output is expected for a line.
|
||||
bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const;
|
||||
|
||||
/// \brief Check if there are any sub-views attached to this view.
|
||||
bool hasSubViews() const;
|
||||
|
||||
SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
|
||||
const CoverageViewOptions &Options,
|
||||
CoverageData &&CoverageInfo)
|
||||
: SourceName(SourceName), File(File), Options(Options),
|
||||
CoverageInfo(std::move(CoverageInfo)) {}
|
||||
|
||||
public:
|
||||
static std::unique_ptr<SourceCoverageView>
|
||||
create(StringRef SourceName, const MemoryBuffer &File,
|
||||
const CoverageViewOptions &Options, CoverageData &&CoverageInfo);
|
||||
|
||||
virtual ~SourceCoverageView() {}
|
||||
|
||||
/// \brief Return the source name formatted for the host OS.
|
||||
std::string getSourceName() const;
|
||||
|
||||
const CoverageViewOptions &getOptions() const { return Options; }
|
||||
|
||||
/// \brief Add an expansion subview to this view.
|
||||
void addExpansion(const CounterMappingRegion &Region,
|
||||
std::unique_ptr<SourceCoverageView> View);
|
||||
|
||||
/// \brief Add a function instantiation subview to this view.
|
||||
void addInstantiation(StringRef FunctionName, unsigned Line,
|
||||
std::unique_ptr<SourceCoverageView> View);
|
||||
|
||||
/// \brief Print the code coverage information for a specific portion of a
|
||||
/// source file to the output stream.
|
||||
void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
|
||||
bool ShowTitle, unsigned ViewDepth = 0);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_COV_SOURCECOVERAGEVIEW_H
|
File diff suppressed because it is too large
Load Diff
@ -1,98 +0,0 @@
|
||||
//===- SourceCoverageViewHTML.h - A html code coverage view ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file This file defines the interface to the html coverage renderer.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_SOURCECOVERAGEVIEWHTML_H
|
||||
#define LLVM_COV_SOURCECOVERAGEVIEWHTML_H
|
||||
|
||||
#include "SourceCoverageView.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
using namespace coverage;
|
||||
|
||||
struct FileCoverageSummary;
|
||||
|
||||
/// \brief A coverage printer for html output.
|
||||
class CoveragePrinterHTML : public CoveragePrinter {
|
||||
public:
|
||||
Expected<OwnedStream> createViewFile(StringRef Path,
|
||||
bool InToplevel) override;
|
||||
|
||||
void closeViewFile(OwnedStream OS) override;
|
||||
|
||||
Error createIndexFile(ArrayRef<std::string> SourceFiles,
|
||||
const coverage::CoverageMapping &Coverage,
|
||||
const CoverageFiltersMatchAll &Filters) override;
|
||||
|
||||
CoveragePrinterHTML(const CoverageViewOptions &Opts)
|
||||
: CoveragePrinter(Opts) {}
|
||||
|
||||
private:
|
||||
void emitFileSummary(raw_ostream &OS, StringRef SF,
|
||||
const FileCoverageSummary &FCS,
|
||||
bool IsTotals = false) const;
|
||||
std::string buildLinkToFile(StringRef SF,
|
||||
const FileCoverageSummary &FCS) const;
|
||||
};
|
||||
|
||||
/// \brief A code coverage view which supports html-based rendering.
|
||||
class SourceCoverageViewHTML : public SourceCoverageView {
|
||||
void renderViewHeader(raw_ostream &OS) override;
|
||||
|
||||
void renderViewFooter(raw_ostream &OS) override;
|
||||
|
||||
void renderSourceName(raw_ostream &OS, bool WholeFile) override;
|
||||
|
||||
void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
void renderLine(raw_ostream &OS, LineRef L, const LineCoverageStats &LCS,
|
||||
unsigned ExpansionCol, unsigned ViewDepth) override;
|
||||
|
||||
void renderExpansionSite(raw_ostream &OS, LineRef L,
|
||||
const LineCoverageStats &LCS, unsigned ExpansionCol,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderLineCoverageColumn(raw_ostream &OS,
|
||||
const LineCoverageStats &Line) override;
|
||||
|
||||
void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
|
||||
|
||||
void renderRegionMarkers(raw_ostream &OS, const LineCoverageStats &Line,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderTitle(raw_ostream &OS, StringRef Title) override;
|
||||
|
||||
void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
|
||||
unsigned IndentLevel) override;
|
||||
|
||||
public:
|
||||
SourceCoverageViewHTML(StringRef SourceName, const MemoryBuffer &File,
|
||||
const CoverageViewOptions &Options,
|
||||
coverage::CoverageData &&CoverageInfo)
|
||||
: SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_COV_SOURCECOVERAGEVIEWHTML_H
|
@ -1,252 +0,0 @@
|
||||
//===- SourceCoverageViewText.cpp - A text-based code coverage view -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file This file implements the text-based coverage renderer.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CoverageReport.h"
|
||||
#include "SourceCoverageViewText.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Expected<CoveragePrinter::OwnedStream>
|
||||
CoveragePrinterText::createViewFile(StringRef Path, bool InToplevel) {
|
||||
return createOutputStream(Path, "txt", InToplevel);
|
||||
}
|
||||
|
||||
void CoveragePrinterText::closeViewFile(OwnedStream OS) {
|
||||
OS->operator<<('\n');
|
||||
}
|
||||
|
||||
Error CoveragePrinterText::createIndexFile(
|
||||
ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage,
|
||||
const CoverageFiltersMatchAll &Filters) {
|
||||
auto OSOrErr = createOutputStream("index", "txt", /*InToplevel=*/true);
|
||||
if (Error E = OSOrErr.takeError())
|
||||
return E;
|
||||
auto OS = std::move(OSOrErr.get());
|
||||
raw_ostream &OSRef = *OS.get();
|
||||
|
||||
CoverageReport Report(Opts, Coverage);
|
||||
Report.renderFileReports(OSRef, SourceFiles, Filters);
|
||||
|
||||
Opts.colored_ostream(OSRef, raw_ostream::CYAN) << "\n"
|
||||
<< Opts.getLLVMVersionString();
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static const unsigned LineCoverageColumnWidth = 7;
|
||||
static const unsigned LineNumberColumnWidth = 5;
|
||||
|
||||
/// \brief Get the width of the leading columns.
|
||||
unsigned getCombinedColumnWidth(const CoverageViewOptions &Opts) {
|
||||
return (Opts.ShowLineStats ? LineCoverageColumnWidth + 1 : 0) +
|
||||
(Opts.ShowLineNumbers ? LineNumberColumnWidth + 1 : 0);
|
||||
}
|
||||
|
||||
/// \brief The width of the line that is used to divide between the view and
|
||||
/// the subviews.
|
||||
unsigned getDividerWidth(const CoverageViewOptions &Opts) {
|
||||
return getCombinedColumnWidth(Opts) + 4;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void SourceCoverageViewText::renderViewHeader(raw_ostream &) {}
|
||||
|
||||
void SourceCoverageViewText::renderViewFooter(raw_ostream &) {}
|
||||
|
||||
void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile) {
|
||||
getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
|
||||
<< ":\n";
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderLinePrefix(raw_ostream &OS,
|
||||
unsigned ViewDepth) {
|
||||
for (unsigned I = 0; I < ViewDepth; ++I)
|
||||
OS << " |";
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderLineSuffix(raw_ostream &, unsigned) {}
|
||||
|
||||
void SourceCoverageViewText::renderViewDivider(raw_ostream &OS,
|
||||
unsigned ViewDepth) {
|
||||
assert(ViewDepth != 0 && "Cannot render divider at top level");
|
||||
renderLinePrefix(OS, ViewDepth - 1);
|
||||
OS.indent(2);
|
||||
unsigned Length = getDividerWidth(getOptions());
|
||||
for (unsigned I = 0; I < Length; ++I)
|
||||
OS << '-';
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderLine(raw_ostream &OS, LineRef L,
|
||||
const LineCoverageStats &LCS,
|
||||
unsigned ExpansionCol,
|
||||
unsigned ViewDepth) {
|
||||
StringRef Line = L.Line;
|
||||
unsigned LineNumber = L.LineNo;
|
||||
auto *WrappedSegment = LCS.getWrappedSegment();
|
||||
CoverageSegmentArray Segments = LCS.getLineSegments();
|
||||
|
||||
Optional<raw_ostream::Colors> Highlight;
|
||||
SmallVector<std::pair<unsigned, unsigned>, 2> HighlightedRanges;
|
||||
|
||||
// The first segment overlaps from a previous line, so we treat it specially.
|
||||
if (WrappedSegment && !WrappedSegment->IsGapRegion &&
|
||||
WrappedSegment->HasCount && WrappedSegment->Count == 0)
|
||||
Highlight = raw_ostream::RED;
|
||||
|
||||
// Output each segment of the line, possibly highlighted.
|
||||
unsigned Col = 1;
|
||||
for (const auto *S : Segments) {
|
||||
unsigned End = std::min(S->Col, static_cast<unsigned>(Line.size()) + 1);
|
||||
colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR,
|
||||
getOptions().Colors && Highlight, /*Bold=*/false,
|
||||
/*BG=*/true)
|
||||
<< Line.substr(Col - 1, End - Col);
|
||||
if (getOptions().Debug && Highlight)
|
||||
HighlightedRanges.push_back(std::make_pair(Col, End));
|
||||
Col = End;
|
||||
if ((!S->IsGapRegion || (Highlight && *Highlight == raw_ostream::RED)) &&
|
||||
S->HasCount && S->Count == 0)
|
||||
Highlight = raw_ostream::RED;
|
||||
else if (Col == ExpansionCol)
|
||||
Highlight = raw_ostream::CYAN;
|
||||
else
|
||||
Highlight = None;
|
||||
}
|
||||
|
||||
// Show the rest of the line.
|
||||
colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR,
|
||||
getOptions().Colors && Highlight, /*Bold=*/false, /*BG=*/true)
|
||||
<< Line.substr(Col - 1, Line.size() - Col + 1);
|
||||
OS << '\n';
|
||||
|
||||
if (getOptions().Debug) {
|
||||
for (const auto &Range : HighlightedRanges)
|
||||
errs() << "Highlighted line " << LineNumber << ", " << Range.first
|
||||
<< " -> " << Range.second << '\n';
|
||||
if (Highlight)
|
||||
errs() << "Highlighted line " << LineNumber << ", " << Col << " -> ?\n";
|
||||
}
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderLineCoverageColumn(
|
||||
raw_ostream &OS, const LineCoverageStats &Line) {
|
||||
if (!Line.isMapped()) {
|
||||
OS.indent(LineCoverageColumnWidth) << '|';
|
||||
return;
|
||||
}
|
||||
std::string C = formatCount(Line.getExecutionCount());
|
||||
OS.indent(LineCoverageColumnWidth - C.size());
|
||||
colored_ostream(OS, raw_ostream::MAGENTA,
|
||||
Line.hasMultipleRegions() && getOptions().Colors)
|
||||
<< C;
|
||||
OS << '|';
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderLineNumberColumn(raw_ostream &OS,
|
||||
unsigned LineNo) {
|
||||
SmallString<32> Buffer;
|
||||
raw_svector_ostream BufferOS(Buffer);
|
||||
BufferOS << LineNo;
|
||||
auto Str = BufferOS.str();
|
||||
// Trim and align to the right.
|
||||
Str = Str.substr(0, std::min(Str.size(), (size_t)LineNumberColumnWidth));
|
||||
OS.indent(LineNumberColumnWidth - Str.size()) << Str << '|';
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderRegionMarkers(raw_ostream &OS,
|
||||
const LineCoverageStats &Line,
|
||||
unsigned ViewDepth) {
|
||||
renderLinePrefix(OS, ViewDepth);
|
||||
OS.indent(getCombinedColumnWidth(getOptions()));
|
||||
|
||||
CoverageSegmentArray Segments = Line.getLineSegments();
|
||||
|
||||
// Just consider the segments which start *and* end on this line.
|
||||
if (Segments.size() > 1)
|
||||
Segments = Segments.drop_back();
|
||||
|
||||
unsigned PrevColumn = 1;
|
||||
for (const auto *S : Segments) {
|
||||
if (!S->IsRegionEntry)
|
||||
continue;
|
||||
if (S->Count == Line.getExecutionCount())
|
||||
continue;
|
||||
// Skip to the new region.
|
||||
if (S->Col > PrevColumn)
|
||||
OS.indent(S->Col - PrevColumn);
|
||||
PrevColumn = S->Col + 1;
|
||||
std::string C = formatCount(S->Count);
|
||||
PrevColumn += C.size();
|
||||
OS << '^' << C;
|
||||
|
||||
if (getOptions().Debug)
|
||||
errs() << "Marker at " << S->Line << ":" << S->Col << " = "
|
||||
<< formatCount(S->Count) << "\n";
|
||||
}
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderExpansionSite(raw_ostream &OS, LineRef L,
|
||||
const LineCoverageStats &LCS,
|
||||
unsigned ExpansionCol,
|
||||
unsigned ViewDepth) {
|
||||
renderLinePrefix(OS, ViewDepth);
|
||||
OS.indent(getCombinedColumnWidth(getOptions()) + (ViewDepth == 0 ? 0 : 1));
|
||||
renderLine(OS, L, LCS, ExpansionCol, ViewDepth);
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderExpansionView(raw_ostream &OS,
|
||||
ExpansionView &ESV,
|
||||
unsigned ViewDepth) {
|
||||
// Render the child subview.
|
||||
if (getOptions().Debug)
|
||||
errs() << "Expansion at line " << ESV.getLine() << ", " << ESV.getStartCol()
|
||||
<< " -> " << ESV.getEndCol() << '\n';
|
||||
ESV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/false,
|
||||
/*ShowTitle=*/false, ViewDepth + 1);
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS,
|
||||
InstantiationView &ISV,
|
||||
unsigned ViewDepth) {
|
||||
renderLinePrefix(OS, ViewDepth);
|
||||
OS << ' ';
|
||||
if (!ISV.View)
|
||||
getOptions().colored_ostream(OS, raw_ostream::RED)
|
||||
<< "Unexecuted instantiation: " << ISV.FunctionName << "\n";
|
||||
else
|
||||
ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true,
|
||||
/*ShowTitle=*/false, ViewDepth);
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderTitle(raw_ostream &OS, StringRef Title) {
|
||||
if (getOptions().hasProjectTitle())
|
||||
getOptions().colored_ostream(OS, raw_ostream::CYAN)
|
||||
<< getOptions().ProjectTitle << "\n";
|
||||
|
||||
getOptions().colored_ostream(OS, raw_ostream::CYAN) << Title << "\n";
|
||||
|
||||
if (getOptions().hasCreatedTime())
|
||||
getOptions().colored_ostream(OS, raw_ostream::CYAN)
|
||||
<< getOptions().CreatedTimeStr << "\n";
|
||||
}
|
||||
|
||||
void SourceCoverageViewText::renderTableHeader(raw_ostream &, unsigned,
|
||||
unsigned) {}
|
@ -1,89 +0,0 @@
|
||||
//===- SourceCoverageViewText.h - A text-based code coverage view ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file This file defines the interface to the text-based coverage renderer.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_COV_SOURCECOVERAGEVIEWTEXT_H
|
||||
#define LLVM_COV_SOURCECOVERAGEVIEWTEXT_H
|
||||
|
||||
#include "SourceCoverageView.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
using namespace coverage;
|
||||
|
||||
/// \brief A coverage printer for text output.
|
||||
class CoveragePrinterText : public CoveragePrinter {
|
||||
public:
|
||||
Expected<OwnedStream> createViewFile(StringRef Path,
|
||||
bool InToplevel) override;
|
||||
|
||||
void closeViewFile(OwnedStream OS) override;
|
||||
|
||||
Error createIndexFile(ArrayRef<std::string> SourceFiles,
|
||||
const CoverageMapping &Coverage,
|
||||
const CoverageFiltersMatchAll &Filters) override;
|
||||
|
||||
CoveragePrinterText(const CoverageViewOptions &Opts)
|
||||
: CoveragePrinter(Opts) {}
|
||||
};
|
||||
|
||||
/// \brief A code coverage view which supports text-based rendering.
|
||||
class SourceCoverageViewText : public SourceCoverageView {
|
||||
void renderViewHeader(raw_ostream &OS) override;
|
||||
|
||||
void renderViewFooter(raw_ostream &OS) override;
|
||||
|
||||
void renderSourceName(raw_ostream &OS, bool WholeFile) override;
|
||||
|
||||
void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
void renderLine(raw_ostream &OS, LineRef L, const LineCoverageStats &LCS,
|
||||
unsigned ExpansionCol, unsigned ViewDepth) override;
|
||||
|
||||
void renderExpansionSite(raw_ostream &OS, LineRef L,
|
||||
const LineCoverageStats &LCS, unsigned ExpansionCol,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderLineCoverageColumn(raw_ostream &OS,
|
||||
const LineCoverageStats &Line) override;
|
||||
|
||||
void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
|
||||
|
||||
void renderRegionMarkers(raw_ostream &OS, const LineCoverageStats &Line,
|
||||
unsigned ViewDepth) override;
|
||||
|
||||
void renderTitle(raw_ostream &OS, StringRef Title) override;
|
||||
|
||||
void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
|
||||
unsigned IndentLevel) override;
|
||||
|
||||
public:
|
||||
SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File,
|
||||
const CoverageViewOptions &Options,
|
||||
CoverageData &&CoverageInfo)
|
||||
: SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_COV_SOURCECOVERAGEVIEWTEXT_H
|
95
external/llvm/tools/llvm-cov/TestingSupport.cpp
vendored
95
external/llvm/tools/llvm-cov/TestingSupport.cpp
vendored
@ -1,95 +0,0 @@
|
||||
//===- TestingSupport.cpp - Convert objects files into test files --------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <functional>
|
||||
#include <system_error>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace object;
|
||||
|
||||
int convertForTestingMain(int argc, const char *argv[]) {
|
||||
cl::opt<std::string> InputSourceFile(cl::Positional, cl::Required,
|
||||
cl::desc("<Source file>"));
|
||||
|
||||
cl::opt<std::string> OutputFilename(
|
||||
"o", cl::Required,
|
||||
cl::desc(
|
||||
"File with the profile data obtained after an instrumented run"));
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
|
||||
|
||||
auto ObjErr = llvm::object::ObjectFile::createObjectFile(InputSourceFile);
|
||||
if (!ObjErr) {
|
||||
std::string Buf;
|
||||
raw_string_ostream OS(Buf);
|
||||
logAllUnhandledErrors(ObjErr.takeError(), OS, "");
|
||||
OS.flush();
|
||||
errs() << "error: " << Buf;
|
||||
return 1;
|
||||
}
|
||||
ObjectFile *OF = ObjErr.get().getBinary();
|
||||
auto BytesInAddress = OF->getBytesInAddress();
|
||||
if (BytesInAddress != 8) {
|
||||
errs() << "error: 64 bit binary expected\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Look for the sections that we are interested in.
|
||||
int FoundSectionCount = 0;
|
||||
SectionRef ProfileNames, CoverageMapping;
|
||||
auto ObjFormat = OF->getTripleObjectFormat();
|
||||
for (const auto &Section : OF->sections()) {
|
||||
StringRef Name;
|
||||
if (Section.getName(Name))
|
||||
return 1;
|
||||
if (Name == llvm::getInstrProfSectionName(IPSK_name, ObjFormat,
|
||||
/*AddSegmentInfo=*/false)) {
|
||||
ProfileNames = Section;
|
||||
} else if (Name == llvm::getInstrProfSectionName(
|
||||
IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) {
|
||||
CoverageMapping = Section;
|
||||
} else
|
||||
continue;
|
||||
++FoundSectionCount;
|
||||
}
|
||||
if (FoundSectionCount != 2)
|
||||
return 1;
|
||||
|
||||
// Get the contents of the given sections.
|
||||
uint64_t ProfileNamesAddress = ProfileNames.getAddress();
|
||||
StringRef CoverageMappingData;
|
||||
StringRef ProfileNamesData;
|
||||
if (CoverageMapping.getContents(CoverageMappingData) ||
|
||||
ProfileNames.getContents(ProfileNamesData))
|
||||
return 1;
|
||||
|
||||
int FD;
|
||||
if (auto Err =
|
||||
sys::fs::openFileForWrite(OutputFilename, FD, sys::fs::F_None)) {
|
||||
errs() << "error: " << Err.message() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
raw_fd_ostream OS(FD, true);
|
||||
OS << "llvmcovmtestdata";
|
||||
encodeULEB128(ProfileNamesData.size(), OS);
|
||||
encodeULEB128(ProfileNamesAddress, OS);
|
||||
OS << ProfileNamesData;
|
||||
// Coverage mapping data is expected to have an alignment of 8.
|
||||
for (unsigned Pad = OffsetToAlignment(OS.tell(), 8); Pad; --Pad)
|
||||
OS.write(uint8_t(0));
|
||||
OS << CoverageMappingData;
|
||||
|
||||
return 0;
|
||||
}
|
145
external/llvm/tools/llvm-cov/gcov.cpp
vendored
145
external/llvm/tools/llvm-cov/gcov.cpp
vendored
@ -1,145 +0,0 @@
|
||||
//===- gcov.cpp - GCOV compatible LLVM coverage tool ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// llvm-cov is a command line tools to analyze and report coverage information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ProfileData/GCOV.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include <system_error>
|
||||
using namespace llvm;
|
||||
|
||||
static void reportCoverage(StringRef SourceFile, StringRef ObjectDir,
|
||||
const std::string &InputGCNO,
|
||||
const std::string &InputGCDA, bool DumpGCOV,
|
||||
const GCOV::Options &Options) {
|
||||
SmallString<128> CoverageFileStem(ObjectDir);
|
||||
if (CoverageFileStem.empty()) {
|
||||
// If no directory was specified with -o, look next to the source file.
|
||||
CoverageFileStem = sys::path::parent_path(SourceFile);
|
||||
sys::path::append(CoverageFileStem, sys::path::stem(SourceFile));
|
||||
} else if (sys::fs::is_directory(ObjectDir))
|
||||
// A directory name was given. Use it and the source file name.
|
||||
sys::path::append(CoverageFileStem, sys::path::stem(SourceFile));
|
||||
else
|
||||
// A file was given. Ignore the source file and look next to this file.
|
||||
sys::path::replace_extension(CoverageFileStem, "");
|
||||
|
||||
std::string GCNO = InputGCNO.empty()
|
||||
? std::string(CoverageFileStem.str()) + ".gcno"
|
||||
: InputGCNO;
|
||||
std::string GCDA = InputGCDA.empty()
|
||||
? std::string(CoverageFileStem.str()) + ".gcda"
|
||||
: InputGCDA;
|
||||
GCOVFile GF;
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> GCNO_Buff =
|
||||
MemoryBuffer::getFileOrSTDIN(GCNO);
|
||||
if (std::error_code EC = GCNO_Buff.getError()) {
|
||||
errs() << GCNO << ": " << EC.message() << "\n";
|
||||
return;
|
||||
}
|
||||
GCOVBuffer GCNO_GB(GCNO_Buff.get().get());
|
||||
if (!GF.readGCNO(GCNO_GB)) {
|
||||
errs() << "Invalid .gcno File!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> GCDA_Buff =
|
||||
MemoryBuffer::getFileOrSTDIN(GCDA);
|
||||
if (std::error_code EC = GCDA_Buff.getError()) {
|
||||
if (EC != errc::no_such_file_or_directory) {
|
||||
errs() << GCDA << ": " << EC.message() << "\n";
|
||||
return;
|
||||
}
|
||||
// Clear the filename to make it clear we didn't read anything.
|
||||
GCDA = "-";
|
||||
} else {
|
||||
GCOVBuffer GCDA_GB(GCDA_Buff.get().get());
|
||||
if (!GF.readGCDA(GCDA_GB)) {
|
||||
errs() << "Invalid .gcda File!\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (DumpGCOV)
|
||||
GF.print(errs());
|
||||
|
||||
FileInfo FI(Options);
|
||||
GF.collectLineCounts(FI);
|
||||
FI.print(llvm::outs(), SourceFile, GCNO, GCDA);
|
||||
}
|
||||
|
||||
int gcovMain(int argc, const char *argv[]) {
|
||||
cl::list<std::string> SourceFiles(cl::Positional, cl::OneOrMore,
|
||||
cl::desc("SOURCEFILE"));
|
||||
|
||||
cl::opt<bool> AllBlocks("a", cl::Grouping, cl::init(false),
|
||||
cl::desc("Display all basic blocks"));
|
||||
cl::alias AllBlocksA("all-blocks", cl::aliasopt(AllBlocks));
|
||||
|
||||
cl::opt<bool> BranchProb("b", cl::Grouping, cl::init(false),
|
||||
cl::desc("Display branch probabilities"));
|
||||
cl::alias BranchProbA("branch-probabilities", cl::aliasopt(BranchProb));
|
||||
|
||||
cl::opt<bool> BranchCount("c", cl::Grouping, cl::init(false),
|
||||
cl::desc("Display branch counts instead "
|
||||
"of percentages (requires -b)"));
|
||||
cl::alias BranchCountA("branch-counts", cl::aliasopt(BranchCount));
|
||||
|
||||
cl::opt<bool> LongNames("l", cl::Grouping, cl::init(false),
|
||||
cl::desc("Prefix filenames with the main file"));
|
||||
cl::alias LongNamesA("long-file-names", cl::aliasopt(LongNames));
|
||||
|
||||
cl::opt<bool> FuncSummary("f", cl::Grouping, cl::init(false),
|
||||
cl::desc("Show coverage for each function"));
|
||||
cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary));
|
||||
|
||||
cl::opt<bool> NoOutput("n", cl::Grouping, cl::init(false),
|
||||
cl::desc("Do not output any .gcov files"));
|
||||
cl::alias NoOutputA("no-output", cl::aliasopt(NoOutput));
|
||||
|
||||
cl::opt<std::string> ObjectDir(
|
||||
"o", cl::value_desc("DIR|FILE"), cl::init(""),
|
||||
cl::desc("Find objects in DIR or based on FILE's path"));
|
||||
cl::alias ObjectDirA("object-directory", cl::aliasopt(ObjectDir));
|
||||
cl::alias ObjectDirB("object-file", cl::aliasopt(ObjectDir));
|
||||
|
||||
cl::opt<bool> PreservePaths("p", cl::Grouping, cl::init(false),
|
||||
cl::desc("Preserve path components"));
|
||||
cl::alias PreservePathsA("preserve-paths", cl::aliasopt(PreservePaths));
|
||||
|
||||
cl::opt<bool> UncondBranch("u", cl::Grouping, cl::init(false),
|
||||
cl::desc("Display unconditional branch info "
|
||||
"(requires -b)"));
|
||||
cl::alias UncondBranchA("unconditional-branches", cl::aliasopt(UncondBranch));
|
||||
|
||||
cl::OptionCategory DebugCat("Internal and debugging options");
|
||||
cl::opt<bool> DumpGCOV("dump", cl::init(false), cl::cat(DebugCat),
|
||||
cl::desc("Dump the gcov file to stderr"));
|
||||
cl::opt<std::string> InputGCNO("gcno", cl::cat(DebugCat), cl::init(""),
|
||||
cl::desc("Override inferred gcno file"));
|
||||
cl::opt<std::string> InputGCDA("gcda", cl::cat(DebugCat), cl::init(""),
|
||||
cl::desc("Override inferred gcda file"));
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
|
||||
|
||||
GCOV::Options Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
|
||||
PreservePaths, UncondBranch, LongNames, NoOutput);
|
||||
|
||||
for (const auto &SourceFile : SourceFiles)
|
||||
reportCoverage(SourceFile, ObjectDir, InputGCNO, InputGCDA, DumpGCOV,
|
||||
Options);
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user