mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-17 11:39:11 +00:00
llvm-cov: Sink some reporting logic into CoverageMapping
This teaches CoverageMapping::getCoveredFunctions to filter to a particular file and uses that to replace most of the logic found in llvm-cov report. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221962 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4a7bbf4c29
commit
d24e90a5de
@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/iterator.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <system_error>
|
||||
@ -240,6 +241,40 @@ struct FunctionRecord {
|
||||
ExecutionCount(ExecutionCount) {}
|
||||
};
|
||||
|
||||
/// \brief Iterator over Functions, optionally filtered to a single file.
|
||||
class FunctionRecordIterator
|
||||
: public iterator_facade_base<FunctionRecordIterator,
|
||||
std::forward_iterator_tag, FunctionRecord> {
|
||||
ArrayRef<FunctionRecord> Records;
|
||||
ArrayRef<FunctionRecord>::iterator Current;
|
||||
StringRef Filename;
|
||||
|
||||
/// \brief Skip records whose primary file is not \c Filename.
|
||||
void skipOtherFiles();
|
||||
|
||||
public:
|
||||
FunctionRecordIterator(ArrayRef<FunctionRecord> Records_,
|
||||
StringRef Filename = "")
|
||||
: Records(Records_), Current(Records.begin()), Filename(Filename) {
|
||||
skipOtherFiles();
|
||||
}
|
||||
|
||||
FunctionRecordIterator() : Current(Records.begin()) {}
|
||||
|
||||
bool operator==(const FunctionRecordIterator &RHS) const {
|
||||
return Current == RHS.Current && Filename == RHS.Filename;
|
||||
}
|
||||
|
||||
const FunctionRecord &operator*() const { return *Current; }
|
||||
|
||||
FunctionRecordIterator &operator++() {
|
||||
assert(Current != Records.end() && "incremented past end");
|
||||
++Current;
|
||||
skipOtherFiles();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Coverage information for a macro expansion or #included file.
|
||||
///
|
||||
/// When covered code has pieces that can be expanded for more detail, such as a
|
||||
@ -342,7 +377,7 @@ public:
|
||||
unsigned getMismatchedCount() { return MismatchedFunctionCount; }
|
||||
|
||||
/// \brief Returns the list of files that are covered.
|
||||
std::vector<StringRef> getUniqueSourceFiles();
|
||||
std::vector<StringRef> getUniqueSourceFiles() const;
|
||||
|
||||
/// \brief Get the coverage for a particular file.
|
||||
///
|
||||
@ -352,8 +387,16 @@ public:
|
||||
CoverageData getCoverageForFile(StringRef Filename);
|
||||
|
||||
/// \brief Gets all of the functions covered by this profile.
|
||||
ArrayRef<FunctionRecord> getCoveredFunctions() {
|
||||
return ArrayRef<FunctionRecord>(Functions.data(), Functions.size());
|
||||
iterator_range<FunctionRecordIterator> getCoveredFunctions() const {
|
||||
return make_range(FunctionRecordIterator(Functions),
|
||||
FunctionRecordIterator());
|
||||
}
|
||||
|
||||
/// \brief Gets all of the functions in a particular file.
|
||||
iterator_range<FunctionRecordIterator>
|
||||
getCoveredFunctions(StringRef Filename) const {
|
||||
return make_range(FunctionRecordIterator(Functions, Filename),
|
||||
FunctionRecordIterator());
|
||||
}
|
||||
|
||||
/// \brief Get the list of function instantiations in the file.
|
||||
|
@ -170,6 +170,14 @@ ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
|
||||
llvm_unreachable("Unhandled CounterKind");
|
||||
}
|
||||
|
||||
void FunctionRecordIterator::skipOtherFiles() {
|
||||
while (Current != Records.end() && !Filename.empty() &&
|
||||
Filename != Current->Filenames[0])
|
||||
++Current;
|
||||
if (Current == Records.end())
|
||||
*this = FunctionRecordIterator();
|
||||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<CoverageMapping>>
|
||||
CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader,
|
||||
IndexedInstrProfReader &ProfileReader) {
|
||||
@ -320,7 +328,7 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() {
|
||||
std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
|
||||
std::vector<StringRef> Filenames;
|
||||
for (const auto &Function : getCoveredFunctions())
|
||||
for (const auto &Filename : Function.Filenames)
|
||||
|
@ -462,7 +462,7 @@ int CodeCoverageTool::report(int argc, const char **argv,
|
||||
return 1;
|
||||
|
||||
CoverageSummary Summarizer;
|
||||
Summarizer.createSummaries(Coverage->getCoveredFunctions());
|
||||
Summarizer.createSummaries(*Coverage);
|
||||
CoverageReport Report(ViewOpts, Summarizer);
|
||||
if (SourceFiles.empty() && Filters.empty()) {
|
||||
Report.renderFileReports(llvm::outs());
|
||||
|
@ -28,44 +28,16 @@ unsigned CoverageSummary::getFileID(StringRef Filename) {
|
||||
}
|
||||
|
||||
void
|
||||
CoverageSummary::createSummaries(ArrayRef<coverage::FunctionRecord> Functions) {
|
||||
std::vector<std::pair<unsigned, size_t>> FunctionFileIDs;
|
||||
|
||||
FunctionFileIDs.resize(Functions.size());
|
||||
for (size_t I = 0, E = Functions.size(); I < E; ++I) {
|
||||
StringRef Filename = Functions[I].Filenames[0];
|
||||
FunctionFileIDs[I] = std::make_pair(getFileID(Filename), I);
|
||||
}
|
||||
|
||||
// Sort the function records by file ids
|
||||
std::sort(FunctionFileIDs.begin(), FunctionFileIDs.end(),
|
||||
[](const std::pair<unsigned, size_t> &lhs,
|
||||
const std::pair<unsigned, size_t> &rhs) {
|
||||
return lhs.first < rhs.first;
|
||||
});
|
||||
|
||||
// Create function summaries in a sorted order (by file ids)
|
||||
FunctionSummaries.reserve(Functions.size());
|
||||
for (size_t I = 0, E = Functions.size(); I < E; ++I)
|
||||
FunctionSummaries.push_back(
|
||||
FunctionCoverageSummary::get(Functions[FunctionFileIDs[I].second]));
|
||||
|
||||
// Create file summaries
|
||||
size_t CurrentSummary = 0;
|
||||
for (unsigned FileID = 0; FileID < Filenames.size(); ++FileID) {
|
||||
// Gather the relevant functions summaries
|
||||
auto PrevSummary = CurrentSummary;
|
||||
while (CurrentSummary < FunctionSummaries.size() &&
|
||||
FunctionFileIDs[CurrentSummary].first == FileID)
|
||||
++CurrentSummary;
|
||||
ArrayRef<FunctionCoverageSummary> LocalSummaries(
|
||||
FunctionSummaries.data() + PrevSummary,
|
||||
FunctionSummaries.data() + CurrentSummary);
|
||||
if (LocalSummaries.empty())
|
||||
CoverageSummary::createSummaries(const coverage::CoverageMapping &Coverage) {
|
||||
for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
|
||||
size_t PrevSize = FunctionSummaries.size();
|
||||
for (const auto &F : Coverage.getCoveredFunctions(Filename))
|
||||
FunctionSummaries.push_back(FunctionCoverageSummary::get(F));
|
||||
size_t Count = FunctionSummaries.size() - PrevSize;
|
||||
if (Count == 0)
|
||||
continue;
|
||||
|
||||
FileSummaries.push_back(
|
||||
FileCoverageSummary::get(Filenames[FileID], LocalSummaries));
|
||||
FileSummaries.push_back(FileCoverageSummary::get(
|
||||
Filename, makeArrayRef(FunctionSummaries.data() + PrevSize, Count)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ class CoverageSummary {
|
||||
unsigned getFileID(StringRef Filename);
|
||||
|
||||
public:
|
||||
void createSummaries(ArrayRef<coverage::FunctionRecord> Functions);
|
||||
void createSummaries(const coverage::CoverageMapping &Coverage);
|
||||
|
||||
ArrayRef<FileCoverageSummary> getFileSummaries() { return FileSummaries; }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user