From d24e90a5deb04f4c024b014158595c36270cfa99 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Fri, 14 Nov 2014 01:50:32 +0000 Subject: [PATCH] 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 --- include/llvm/ProfileData/CoverageMapping.h | 49 ++++++++++++++++++++-- lib/ProfileData/CoverageMapping.cpp | 10 ++++- tools/llvm-cov/CodeCoverage.cpp | 2 +- tools/llvm-cov/CoverageSummary.cpp | 46 ++++---------------- tools/llvm-cov/CoverageSummary.h | 2 +- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index c1f478459b9..38fc8ca7c77 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -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 @@ -240,6 +241,40 @@ struct FunctionRecord { ExecutionCount(ExecutionCount) {} }; +/// \brief Iterator over Functions, optionally filtered to a single file. +class FunctionRecordIterator + : public iterator_facade_base { + ArrayRef Records; + ArrayRef::iterator Current; + StringRef Filename; + + /// \brief Skip records whose primary file is not \c Filename. + void skipOtherFiles(); + +public: + FunctionRecordIterator(ArrayRef 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 getUniqueSourceFiles(); + std::vector 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 getCoveredFunctions() { - return ArrayRef(Functions.data(), Functions.size()); + iterator_range getCoveredFunctions() const { + return make_range(FunctionRecordIterator(Functions), + FunctionRecordIterator()); + } + + /// \brief Gets all of the functions in a particular file. + iterator_range + getCoveredFunctions(StringRef Filename) const { + return make_range(FunctionRecordIterator(Functions, Filename), + FunctionRecordIterator()); } /// \brief Get the list of function instantiations in the file. diff --git a/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp index c7dba2c1340..0ccebc2b97e 100644 --- a/lib/ProfileData/CoverageMapping.cpp +++ b/lib/ProfileData/CoverageMapping.cpp @@ -170,6 +170,14 @@ ErrorOr 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> CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader) { @@ -320,7 +328,7 @@ public: }; } -std::vector CoverageMapping::getUniqueSourceFiles() { +std::vector CoverageMapping::getUniqueSourceFiles() const { std::vector Filenames; for (const auto &Function : getCoveredFunctions()) for (const auto &Filename : Function.Filenames) diff --git a/tools/llvm-cov/CodeCoverage.cpp b/tools/llvm-cov/CodeCoverage.cpp index d6fe9d34712..093525eb3dd 100644 --- a/tools/llvm-cov/CodeCoverage.cpp +++ b/tools/llvm-cov/CodeCoverage.cpp @@ -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()); diff --git a/tools/llvm-cov/CoverageSummary.cpp b/tools/llvm-cov/CoverageSummary.cpp index 785e9024ba7..059c8c857e4 100644 --- a/tools/llvm-cov/CoverageSummary.cpp +++ b/tools/llvm-cov/CoverageSummary.cpp @@ -28,44 +28,16 @@ unsigned CoverageSummary::getFileID(StringRef Filename) { } void -CoverageSummary::createSummaries(ArrayRef Functions) { - std::vector> 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 &lhs, - const std::pair &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 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))); } } diff --git a/tools/llvm-cov/CoverageSummary.h b/tools/llvm-cov/CoverageSummary.h index b93103c8cf2..9dbebde949e 100644 --- a/tools/llvm-cov/CoverageSummary.h +++ b/tools/llvm-cov/CoverageSummary.h @@ -30,7 +30,7 @@ class CoverageSummary { unsigned getFileID(StringRef Filename); public: - void createSummaries(ArrayRef Functions); + void createSummaries(const coverage::CoverageMapping &Coverage); ArrayRef getFileSummaries() { return FileSummaries; } -- 2.34.1