diff options
Diffstat (limited to 'llvm/tools/llvm-cov')
-rw-r--r-- | llvm/tools/llvm-cov/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CodeCoverage.cpp | 369 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageFilters.cpp | 14 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageFilters.h | 18 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageSummary.cpp | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageSummary.h | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageSummaryInfo.cpp | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageSummaryInfo.h | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageDataManager.cpp | 104 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageDataManager.h | 53 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageView.cpp | 22 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageView.h | 23 |
12 files changed, 137 insertions, 477 deletions
diff --git a/llvm/tools/llvm-cov/CMakeLists.txt b/llvm/tools/llvm-cov/CMakeLists.txt index 54d9ece3988..b2d2b897ec9 100644 --- a/llvm/tools/llvm-cov/CMakeLists.txt +++ b/llvm/tools/llvm-cov/CMakeLists.txt @@ -8,7 +8,6 @@ add_llvm_tool(llvm-cov CoverageReport.cpp CoverageSummary.cpp CoverageSummaryInfo.cpp - SourceCoverageDataManager.cpp SourceCoverageView.cpp TestingSupport.cpp ) diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 1a5d6a50f9e..5fc5a849cec 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -16,15 +16,11 @@ #include "RenderingSupport.h" #include "CoverageViewOptions.h" #include "CoverageFilters.h" -#include "SourceCoverageDataManager.h" #include "SourceCoverageView.h" #include "CoverageSummary.h" #include "CoverageReport.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ProfileData/CoverageMappingReader.h" @@ -43,34 +39,6 @@ using namespace llvm; using namespace coverage; namespace { -/// \brief Distribute the functions into instantiation sets. -/// -/// An instantiation set is a collection of functions that have the same source -/// code, ie, template functions specializations. -class FunctionInstantiationSetCollector { - typedef DenseMap<std::pair<unsigned, unsigned>, - std::vector<const FunctionCoverageMapping *>> MapT; - MapT InstantiatedFunctions; - -public: - void insert(const FunctionCoverageMapping &Function, unsigned FileID) { - auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end(); - while (I != E && I->FileID != FileID) - ++I; - assert(I != E && "function does not cover the given file"); - auto &Functions = InstantiatedFunctions[I->startLoc()]; - Functions.push_back(&Function); - } - - MapT::iterator begin() { - return InstantiatedFunctions.begin(); - } - - MapT::iterator end() { - return InstantiatedFunctions.end(); - } -}; - /// \brief The implementation of the coverage tool. class CodeCoverageTool { public: @@ -87,43 +55,21 @@ public: /// \brief Return a memory buffer for the given source file. ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile); - /// \brief Collect a set of function's file ids which correspond to the - /// given source file. Return false if the set is empty. - bool gatherInterestingFileIDs(StringRef SourceFile, - const FunctionCoverageMapping &Function, - SmallSet<unsigned, 8> &InterestingFileIDs); + /// \brief Create source views for the expansions of the view. + void attachExpansionSubViews(SourceCoverageView &View, + ArrayRef<ExpansionRecord> Expansions, + CoverageMapping &Coverage); - /// \brief Find the file id which is not an expanded file id. - bool findMainViewFileID(StringRef SourceFile, - const FunctionCoverageMapping &Function, - unsigned &MainViewFileID); - - bool findMainViewFileID(const FunctionCoverageMapping &Function, - unsigned &MainViewFileID); - - /// \brief Create a source view which shows coverage for an expansion - /// of a file. - std::unique_ptr<SourceCoverageView> - createExpansionSubView(const CountedRegion &ExpandedRegion, - const FunctionCoverageMapping &Function); - - void attachExpansionSubViews(SourceCoverageView &View, unsigned ViewFileID, - const FunctionCoverageMapping &Function); - - /// \brief Create a source view which shows coverage for an instantiation - /// of a funciton. + /// \brief Create the source view of a particular function. std::unique_ptr<SourceCoverageView> - createInstantiationSubView(StringRef SourceFile, - const FunctionCoverageMapping &Function); + createFunctionView(const FunctionRecord &Function, CoverageMapping &Coverage); /// \brief Create the main source view of a particular source file. std::unique_ptr<SourceCoverageView> - createSourceFileView(StringRef SourceFile, - ArrayRef<FunctionCoverageMapping> FunctionMappingRecords, - bool UseOnlyRegionsInMainFile = false); + createSourceFileView(StringRef SourceFile, CoverageMapping &Coverage); /// \brief Load the coverage mapping data. Return true if an error occured. - bool load(); + std::unique_ptr<CoverageMapping> load(); int run(Command Cmd, int argc, const char **argv); @@ -137,29 +83,16 @@ public: StringRef ObjectFilename; CoverageViewOptions ViewOpts; - std::unique_ptr<IndexedInstrProfReader> PGOReader; + std::string PGOFilename; CoverageFiltersMatchAll Filters; std::vector<std::string> SourceFiles; std::vector<std::pair<std::string, std::unique_ptr<MemoryBuffer>>> LoadedSourceFiles; - std::vector<FunctionCoverageMapping> FunctionMappingRecords; bool CompareFilenamesOnly; StringMap<std::string> RemappedFilenames; }; } -static std::vector<StringRef> -getUniqueFilenames(ArrayRef<FunctionCoverageMapping> FunctionMappingRecords) { - std::vector<StringRef> Filenames; - for (const auto &Function : FunctionMappingRecords) - for (const auto &Filename : Function.Filenames) - Filenames.push_back(Filename); - std::sort(Filenames.begin(), Filenames.end()); - auto Last = std::unique(Filenames.begin(), Filenames.end()); - Filenames.erase(Last, Filenames.end()); - return Filenames; -} - void CodeCoverageTool::error(const Twine &Message, StringRef Whence) { errs() << "error: "; if (!Whence.empty()) @@ -188,219 +121,115 @@ CodeCoverageTool::getSourceFile(StringRef SourceFile) { return *LoadedSourceFiles.back().second; } -bool CodeCoverageTool::gatherInterestingFileIDs( - StringRef SourceFile, const FunctionCoverageMapping &Function, - SmallSet<unsigned, 8> &InterestingFileIDs) { - bool Interesting = false; - for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) { - if (SourceFile == Function.Filenames[I]) { - InterestingFileIDs.insert(I); - Interesting = true; - } - } - return Interesting; -} - -bool -CodeCoverageTool::findMainViewFileID(StringRef SourceFile, - const FunctionCoverageMapping &Function, - unsigned &MainViewFileID) { - llvm::SmallVector<bool, 8> IsExpandedFile(Function.Filenames.size(), false); - llvm::SmallVector<bool, 8> FilenameEquivalence(Function.Filenames.size(), - false); - for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) { - if (SourceFile == Function.Filenames[I]) - FilenameEquivalence[I] = true; - } - for (const auto &CR : Function.CountedRegions) { - if (CR.Kind == CounterMappingRegion::ExpansionRegion && - FilenameEquivalence[CR.FileID]) - IsExpandedFile[CR.ExpandedFileID] = true; - } - for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) { - if (!FilenameEquivalence[I] || IsExpandedFile[I]) - continue; - MainViewFileID = I; - return false; - } - return true; -} - -bool -CodeCoverageTool::findMainViewFileID(const FunctionCoverageMapping &Function, - unsigned &MainViewFileID) { - llvm::SmallVector<bool, 8> IsExpandedFile(Function.Filenames.size(), false); - for (const auto &CR : Function.CountedRegions) { - if (CR.Kind == CounterMappingRegion::ExpansionRegion) - IsExpandedFile[CR.ExpandedFileID] = true; - } - for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) { - if (IsExpandedFile[I]) - continue; - MainViewFileID = I; - return false; - } - return true; -} - -std::unique_ptr<SourceCoverageView> CodeCoverageTool::createExpansionSubView( - const CountedRegion &ExpandedRegion, - const FunctionCoverageMapping &Function) { - auto SourceBuffer = - getSourceFile(Function.Filenames[ExpandedRegion.ExpandedFileID]); - if (!SourceBuffer) - return nullptr; - auto RegionManager = llvm::make_unique<SourceCoverageDataManager>(); - for (const auto &CR : Function.CountedRegions) { - if (CR.FileID == ExpandedRegion.ExpandedFileID) - RegionManager->insert(CR); - } - auto SubView = llvm::make_unique<SourceCoverageView>(SourceBuffer.get(), - ViewOpts); - SubView->load(std::move(RegionManager)); - attachExpansionSubViews(*SubView, ExpandedRegion.ExpandedFileID, Function); - return SubView; -} - -void CodeCoverageTool::attachExpansionSubViews( - SourceCoverageView &View, unsigned ViewFileID, - const FunctionCoverageMapping &Function) { +void +CodeCoverageTool::attachExpansionSubViews(SourceCoverageView &View, + ArrayRef<ExpansionRecord> Expansions, + CoverageMapping &Coverage) { if (!ViewOpts.ShowExpandedRegions) return; - for (const auto &CR : Function.CountedRegions) { - if (CR.Kind != CounterMappingRegion::ExpansionRegion) + for (const auto &Expansion : Expansions) { + auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion); + if (ExpansionCoverage.empty()) continue; - if (CR.FileID != ViewFileID) + auto SourceBuffer = getSourceFile(ExpansionCoverage.getFilename()); + if (!SourceBuffer) continue; - auto SubView = createExpansionSubView(CR, Function); - if (SubView) - View.addExpansion(CR, std::move(SubView)); + + auto SubViewExpansions = ExpansionCoverage.getExpansions(); + auto SubView = llvm::make_unique<SourceCoverageView>( + SourceBuffer.get(), ViewOpts, std::move(ExpansionCoverage)); + attachExpansionSubViews(*SubView, SubViewExpansions, Coverage); + View.addExpansion(Expansion.Region, std::move(SubView)); } } std::unique_ptr<SourceCoverageView> -CodeCoverageTool::createInstantiationSubView( - StringRef SourceFile, const FunctionCoverageMapping &Function) { - auto RegionManager = llvm::make_unique<SourceCoverageDataManager>(); - SmallSet<unsigned, 8> InterestingFileIDs; - if (!gatherInterestingFileIDs(SourceFile, Function, InterestingFileIDs)) +CodeCoverageTool::createFunctionView(const FunctionRecord &Function, + CoverageMapping &Coverage) { + auto FunctionCoverage = Coverage.getCoverageForFunction(Function); + if (FunctionCoverage.empty()) return nullptr; - // Get the interesting regions - for (const auto &CR : Function.CountedRegions) { - if (InterestingFileIDs.count(CR.FileID)) - RegionManager->insert(CR); - } - - auto SourceBuffer = getSourceFile(SourceFile); + auto SourceBuffer = getSourceFile(FunctionCoverage.getFilename()); if (!SourceBuffer) return nullptr; - auto SubView = llvm::make_unique<SourceCoverageView>(SourceBuffer.get(), - ViewOpts); - SubView->load(std::move(RegionManager)); - unsigned MainFileID; - if (!findMainViewFileID(SourceFile, Function, MainFileID)) - attachExpansionSubViews(*SubView, MainFileID, Function); - return SubView; -} -std::unique_ptr<SourceCoverageView> CodeCoverageTool::createSourceFileView( - StringRef SourceFile, - ArrayRef<FunctionCoverageMapping> FunctionMappingRecords, - bool UseOnlyRegionsInMainFile) { - auto RegionManager = llvm::make_unique<SourceCoverageDataManager>(); - FunctionInstantiationSetCollector InstantiationSetCollector; + auto Expansions = FunctionCoverage.getExpansions(); + auto View = llvm::make_unique<SourceCoverageView>( + SourceBuffer.get(), ViewOpts, std::move(FunctionCoverage)); + attachExpansionSubViews(*View, Expansions, Coverage); + + return View; +} +std::unique_ptr<SourceCoverageView> +CodeCoverageTool::createSourceFileView(StringRef SourceFile, + CoverageMapping &Coverage) { auto SourceBuffer = getSourceFile(SourceFile); if (!SourceBuffer) return nullptr; - auto View = - llvm::make_unique<SourceCoverageView>(SourceBuffer.get(), ViewOpts); - - for (const auto &Function : FunctionMappingRecords) { - unsigned MainFileID; - if (findMainViewFileID(SourceFile, Function, MainFileID)) - continue; - SmallSet<unsigned, 8> InterestingFileIDs; - if (UseOnlyRegionsInMainFile) { - InterestingFileIDs.insert(MainFileID); - } else if (!gatherInterestingFileIDs(SourceFile, Function, - InterestingFileIDs)) - continue; - // Get the interesting regions - for (const auto &CR : Function.CountedRegions) { - if (InterestingFileIDs.count(CR.FileID)) - RegionManager->insert(CR); - } - InstantiationSetCollector.insert(Function, MainFileID); - attachExpansionSubViews(*View, MainFileID, Function); - } - if (RegionManager->getCoverageSegments().empty()) + auto FileCoverage = Coverage.getCoverageForFile(SourceFile); + if (FileCoverage.empty()) return nullptr; - View->load(std::move(RegionManager)); - // Show instantiations - if (!ViewOpts.ShowFunctionInstantiations) - return View; - for (const auto &InstantiationSet : InstantiationSetCollector) { - if (InstantiationSet.second.size() < 2) - continue; - for (auto Function : InstantiationSet.second) { + + auto Expansions = FileCoverage.getExpansions(); + auto View = llvm::make_unique<SourceCoverageView>( + SourceBuffer.get(), ViewOpts, std::move(FileCoverage)); + attachExpansionSubViews(*View, Expansions, Coverage); + + for (auto Function : Coverage.getInstantiations(SourceFile)) { + auto SubViewCoverage = Coverage.getCoverageForFunction(*Function); + auto SubViewExpansions = SubViewCoverage.getExpansions(); + auto SubView = llvm::make_unique<SourceCoverageView>( + SourceBuffer.get(), ViewOpts, std::move(SubViewCoverage)); + attachExpansionSubViews(*SubView, SubViewExpansions, Coverage); + + if (SubView) { unsigned FileID = Function->CountedRegions.front().FileID; unsigned Line = 0; for (const auto &CR : Function->CountedRegions) if (CR.FileID == FileID) Line = std::max(CR.LineEnd, Line); - auto SubView = createInstantiationSubView(SourceFile, *Function); - if (SubView) - View->addInstantiation(Function->Name, Line, std::move(SubView)); + View->addInstantiation(Function->Name, Line, std::move(SubView)); } } return View; } -bool CodeCoverageTool::load() { +std::unique_ptr<CoverageMapping> CodeCoverageTool::load() { auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename); if (auto EC = CounterMappingBuff.getError()) { error(EC.message(), ObjectFilename); - return true; + return nullptr; } ObjectFileCoverageMappingReader MappingReader(CounterMappingBuff.get()); if (auto EC = MappingReader.readHeader()) { error(EC.message(), ObjectFilename); - return true; + return nullptr; } - std::vector<uint64_t> Counts; - for (const auto &I : MappingReader) { - FunctionCoverageMapping Function(I.FunctionName, I.Filenames); - - // Create the mapping regions with evaluated execution counts - Counts.clear(); - PGOReader->getFunctionCounts(Function.Name, I.FunctionHash, Counts); - - // Get the biggest referenced counters - bool RegionError = false; - CounterMappingContext Ctx(I.Expressions, Counts); - for (const auto &R : I.MappingRegions) { - ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(R.Count); - if (ExecutionCount) { - Function.CountedRegions.push_back(CountedRegion(R, *ExecutionCount)); - } else if (!RegionError) { - colored_ostream(errs(), raw_ostream::RED) - << "error: Regions and counters don't match in a function '" - << Function.Name << "' (re-run the instrumented binary)."; - errs() << "\n"; - RegionError = true; - } - } - - if (RegionError || !Filters.matches(Function)) - continue; + std::unique_ptr<IndexedInstrProfReader> PGOReader; + if (auto EC = IndexedInstrProfReader::create(PGOFilename, PGOReader)) { + error(EC.message(), PGOFilename); + return nullptr; + } - FunctionMappingRecords.push_back(Function); + auto CoverageOrErr = CoverageMapping::load(MappingReader, *PGOReader); + if (std::error_code EC = CoverageOrErr.getError()) { + colored_ostream(errs(), raw_ostream::RED) + << "error: Failed to load coverage: " << EC.message(); + errs() << "\n"; + return nullptr; + } + auto Coverage = std::move(CoverageOrErr.get()); + unsigned Mismatched = Coverage->getMismatchedCount(); + if (Mismatched) { + colored_ostream(errs(), raw_ostream::RED) + << "warning: " << Mismatched << " functions have mismatched data. "; + errs() << "\n"; } if (CompareFilenamesOnly) { - auto CoveredFiles = getUniqueFilenames(FunctionMappingRecords); + auto CoveredFiles = Coverage.get()->getUniqueSourceFiles(); for (auto &SF : SourceFiles) { StringRef SFBase = sys::path::filename(SF); for (const auto &CF : CoveredFiles) @@ -412,7 +241,7 @@ bool CodeCoverageTool::load() { } } - return false; + return Coverage; } int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { @@ -424,8 +253,8 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { cl::list<std::string> InputSourceFiles( cl::Positional, cl::desc("<Source files>"), cl::ZeroOrMore); - cl::opt<std::string> PGOFilename( - "instr-profile", cl::Required, + cl::opt<std::string, true> PGOFilename( + "instr-profile", cl::Required, cl::location(this->PGOFilename), cl::desc( "File with the profile data obtained after an instrumented run")); @@ -479,11 +308,6 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { ViewOpts.Debug = DebugDump; CompareFilenamesOnly = FilenameEquivalence; - if (auto EC = IndexedInstrProfReader::create(PGOFilename, PGOReader)) { - error(EC.message(), PGOFilename); - return 1; - } - // Create the function filters if (!NameFilters.empty() || !NameRegexFilters.empty()) { auto NameFilterer = new CoverageFilters; @@ -597,30 +421,28 @@ int CodeCoverageTool::show(int argc, const char **argv, ViewOpts.ShowExpandedRegions = ShowExpansions; ViewOpts.ShowFunctionInstantiations = ShowInstantiations; - if (load()) + auto Coverage = load(); + if (!Coverage) return 1; if (!Filters.empty()) { // Show functions - for (const auto &Function : FunctionMappingRecords) { - unsigned MainFileID; - if (findMainViewFileID(Function, MainFileID)) + for (const auto &Function : Coverage->getCoveredFunctions()) { + if (!Filters.matches(Function)) continue; - StringRef SourceFile = Function.Filenames[MainFileID]; - auto mainView = createSourceFileView(SourceFile, Function, true); + + auto mainView = createFunctionView(Function, *Coverage); if (!mainView) { ViewOpts.colored_ostream(outs(), raw_ostream::RED) - << "warning: Could not read coverage for '" << Function.Name - << " from " << SourceFile; + << "warning: Could not read coverage for '" << Function.Name; outs() << "\n"; continue; } - ViewOpts.colored_ostream(outs(), raw_ostream::CYAN) - << Function.Name << " from " << SourceFile << ":"; + ViewOpts.colored_ostream(outs(), raw_ostream::CYAN) << Function.Name + << ":"; outs() << "\n"; mainView->render(outs(), /*WholeFile=*/false); - if (FunctionMappingRecords.size() > 1) - outs() << "\n"; + outs() << "\n"; } return 0; } @@ -630,11 +452,11 @@ int CodeCoverageTool::show(int argc, const char **argv, if (SourceFiles.empty()) // Get the source files from the function coverage mapping - for (StringRef Filename : getUniqueFilenames(FunctionMappingRecords)) + for (StringRef Filename : Coverage->getUniqueSourceFiles()) SourceFiles.push_back(Filename); for (const auto &SourceFile : SourceFiles) { - auto mainView = createSourceFileView(SourceFile, FunctionMappingRecords); + auto mainView = createSourceFileView(SourceFile, *Coverage); if (!mainView) { ViewOpts.colored_ostream(outs(), raw_ostream::RED) << "warning: The file '" << SourceFile << "' isn't covered."; @@ -665,11 +487,12 @@ int CodeCoverageTool::report(int argc, const char **argv, ViewOpts.Colors = !NoColors; - if (load()) + auto Coverage = load(); + if (!Coverage) return 1; CoverageSummary Summarizer; - Summarizer.createSummaries(FunctionMappingRecords); + Summarizer.createSummaries(Coverage->getCoveredFunctions()); CoverageReport Report(ViewOpts, Summarizer); if (SourceFiles.empty() && Filters.empty()) { Report.renderFileReports(llvm::outs()); diff --git a/llvm/tools/llvm-cov/CoverageFilters.cpp b/llvm/tools/llvm-cov/CoverageFilters.cpp index 999a6bbb747..325dd723578 100644 --- a/llvm/tools/llvm-cov/CoverageFilters.cpp +++ b/llvm/tools/llvm-cov/CoverageFilters.cpp @@ -17,21 +17,22 @@ using namespace llvm; -bool NameCoverageFilter::matches(const FunctionCoverageMapping &Function) { +bool NameCoverageFilter::matches(const coverage::FunctionRecord &Function) { StringRef FuncName = Function.Name; return FuncName.find(Name) != StringRef::npos; } -bool NameRegexCoverageFilter::matches(const FunctionCoverageMapping &Function) { +bool +NameRegexCoverageFilter::matches(const coverage::FunctionRecord &Function) { return llvm::Regex(Regex).match(Function.Name); } -bool RegionCoverageFilter::matches(const FunctionCoverageMapping &Function) { +bool RegionCoverageFilter::matches(const coverage::FunctionRecord &Function) { return PassesThreshold(FunctionCoverageSummary::get(Function) .RegionCoverage.getPercentCovered()); } -bool LineCoverageFilter::matches(const FunctionCoverageMapping &Function) { +bool LineCoverageFilter::matches(const coverage::FunctionRecord &Function) { return PassesThreshold( FunctionCoverageSummary::get(Function).LineCoverage.getPercentCovered()); } @@ -40,7 +41,7 @@ void CoverageFilters::push_back(std::unique_ptr<CoverageFilter> Filter) { Filters.push_back(std::move(Filter)); } -bool CoverageFilters::matches(const FunctionCoverageMapping &Function) { +bool CoverageFilters::matches(const coverage::FunctionRecord &Function) { for (const auto &Filter : Filters) { if (Filter->matches(Function)) return true; @@ -48,7 +49,8 @@ bool CoverageFilters::matches(const FunctionCoverageMapping &Function) { return false; } -bool CoverageFiltersMatchAll::matches(const FunctionCoverageMapping &Function) { +bool +CoverageFiltersMatchAll::matches(const coverage::FunctionRecord &Function) { for (const auto &Filter : Filters) { if (!Filter->matches(Function)) return false; diff --git a/llvm/tools/llvm-cov/CoverageFilters.h b/llvm/tools/llvm-cov/CoverageFilters.h index 99ecb791ffc..e543005c6bc 100644 --- a/llvm/tools/llvm-cov/CoverageFilters.h +++ b/llvm/tools/llvm-cov/CoverageFilters.h @@ -20,15 +20,15 @@ namespace llvm { -using coverage::FunctionCoverageMapping; - /// \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 FunctionCoverageMapping &Function) { return true; } + virtual bool matches(const coverage::FunctionRecord &Function) { + return true; + } }; /// \brief Matches functions that contain a specific string in their name. @@ -38,7 +38,7 @@ class NameCoverageFilter : public CoverageFilter { public: NameCoverageFilter(StringRef Name) : Name(Name) {} - bool matches(const FunctionCoverageMapping &Function) override; + bool matches(const coverage::FunctionRecord &Function) override; }; /// \brief Matches functions whose name matches a certain regular expression. @@ -48,7 +48,7 @@ class NameRegexCoverageFilter : public CoverageFilter { public: NameRegexCoverageFilter(StringRef Regex) : Regex(Regex) {} - bool matches(const FunctionCoverageMapping &Function) override; + bool matches(const coverage::FunctionRecord &Function) override; }; /// \brief Matches numbers that pass a certain threshold. @@ -84,7 +84,7 @@ public: RegionCoverageFilter(Operation Op, double Threshold) : StatisticThresholdFilter(Op, Threshold) {} - bool matches(const FunctionCoverageMapping &Function) override; + bool matches(const coverage::FunctionRecord &Function) override; }; /// \brief Matches functions whose line coverage percentage @@ -95,7 +95,7 @@ public: LineCoverageFilter(Operation Op, double Threshold) : StatisticThresholdFilter(Op, Threshold) {} - bool matches(const FunctionCoverageMapping &Function) override; + bool matches(const coverage::FunctionRecord &Function) override; }; /// \brief A collection of filters. @@ -111,7 +111,7 @@ public: bool empty() const { return Filters.empty(); } - bool matches(const FunctionCoverageMapping &Function) override; + bool matches(const coverage::FunctionRecord &Function) override; }; /// \brief A collection of filters. @@ -119,7 +119,7 @@ public: /// in an instance of this class. class CoverageFiltersMatchAll : public CoverageFilters { public: - bool matches(const FunctionCoverageMapping &Function) override; + bool matches(const coverage::FunctionRecord &Function) override; }; } // namespace llvm diff --git a/llvm/tools/llvm-cov/CoverageSummary.cpp b/llvm/tools/llvm-cov/CoverageSummary.cpp index c65c5bee00f..8df3bebbacf 100644 --- a/llvm/tools/llvm-cov/CoverageSummary.cpp +++ b/llvm/tools/llvm-cov/CoverageSummary.cpp @@ -27,8 +27,8 @@ unsigned CoverageSummary::getFileID(StringRef Filename) { return Filenames.size() - 1; } -void CoverageSummary::createSummaries( - ArrayRef<coverage::FunctionCoverageMapping> Functions) { +void +CoverageSummary::createSummaries(ArrayRef<coverage::FunctionRecord> Functions) { std::vector<std::pair<unsigned, size_t>> FunctionFileIDs; FunctionFileIDs.resize(Functions.size()); diff --git a/llvm/tools/llvm-cov/CoverageSummary.h b/llvm/tools/llvm-cov/CoverageSummary.h index 5d6a55559cd..b93103c8cf2 100644 --- a/llvm/tools/llvm-cov/CoverageSummary.h +++ b/llvm/tools/llvm-cov/CoverageSummary.h @@ -30,7 +30,7 @@ class CoverageSummary { unsigned getFileID(StringRef Filename); public: - void createSummaries(ArrayRef<coverage::FunctionCoverageMapping> Functions); + void createSummaries(ArrayRef<coverage::FunctionRecord> Functions); ArrayRef<FileCoverageSummary> getFileSummaries() { return FileSummaries; } diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp index 53173577d7f..334bc73e0d9 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp @@ -18,7 +18,7 @@ using namespace llvm; using namespace coverage; FunctionCoverageSummary -FunctionCoverageSummary::get(const FunctionCoverageMapping &Function) { +FunctionCoverageSummary::get(const coverage::FunctionRecord &Function) { // Compute the region coverage size_t NumCodeRegions = 0, CoveredRegions = 0; for (auto &CR : Function.CountedRegions) { diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h index 8a40867b3e1..18b270433cd 100644 --- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h +++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h @@ -101,7 +101,7 @@ struct FunctionCoverageSummary { /// \brief Compute the code coverage summary for the given function coverage /// mapping record. static FunctionCoverageSummary - get(const coverage::FunctionCoverageMapping &Function); + get(const coverage::FunctionRecord &Function); }; /// \brief A summary of file's code coverage. diff --git a/llvm/tools/llvm-cov/SourceCoverageDataManager.cpp b/llvm/tools/llvm-cov/SourceCoverageDataManager.cpp deleted file mode 100644 index a60ea6e2586..00000000000 --- a/llvm/tools/llvm-cov/SourceCoverageDataManager.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//===- SourceCoverageDataManager.cpp - Manager for source file coverage -// data-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class separates and merges mapping regions for a specific source file. -// -//===----------------------------------------------------------------------===// - -#include "SourceCoverageDataManager.h" - -using namespace llvm; -using namespace coverage; - -void SourceCoverageDataManager::insert(const CountedRegion &CR) { - Regions.push_back(CR); - Segments.clear(); -} - -namespace { -class SegmentBuilder { - std::vector<CoverageSegment> Segments; - SmallVector<const CountedRegion *, 8> ActiveRegions; - - /// Start a segment with no count specified. - void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry) { - Segments.emplace_back(Line, Col, IsRegionEntry); - } - - /// Start a segment with the given Region's count. - void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry, - const CountedRegion &Region) { - if (Segments.empty()) - Segments.emplace_back(Line, Col, IsRegionEntry); - CoverageSegment S = Segments.back(); - // Avoid creating empty regions. - if (S.Line != Line || S.Col != Col) { - Segments.emplace_back(Line, Col, IsRegionEntry); - S = Segments.back(); - } - // Set this region's count. - if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) - Segments.back().setCount(Region.ExecutionCount); - } - - /// Start a segment for the given region. - void startSegment(const CountedRegion &Region) { - startSegment(Region.LineStart, Region.ColumnStart, true, Region); - } - - /// Pop the top region off of the active stack, starting a new segment with - /// the containing Region's count. - void popRegion() { - const CountedRegion *Active = ActiveRegions.back(); - unsigned Line = Active->LineEnd, Col = Active->ColumnEnd; - ActiveRegions.pop_back(); - if (ActiveRegions.empty()) - startSegment(Line, Col, /*IsRegionEntry=*/false); - else - startSegment(Line, Col, /*IsRegionEntry=*/false, *ActiveRegions.back()); - } - -public: - /// Build a list of CoverageSegments from a sorted list of Regions. - std::vector<CoverageSegment> - buildSegments(ArrayRef<CountedRegion> Regions) { - for (const auto &Region : Regions) { - // Pop any regions that end before this one starts. - while (!ActiveRegions.empty() && - ActiveRegions.back()->endLoc() <= Region.startLoc()) - popRegion(); - // Add this region to the stack. - ActiveRegions.push_back(&Region); - startSegment(Region); - } - // Pop any regions that are left in the stack. - while (!ActiveRegions.empty()) - popRegion(); - return Segments; - } -}; -} - -ArrayRef<CoverageSegment> SourceCoverageDataManager::getCoverageSegments() { - if (Segments.empty()) { - // Sort the regions given that they're all in the same file at this point. - std::sort(Regions.begin(), Regions.end(), - [](const CountedRegion &LHS, const CountedRegion &RHS) { - if (LHS.startLoc() == RHS.startLoc()) - // When LHS completely contains RHS, we sort LHS first. - return RHS.endLoc() < LHS.endLoc(); - return LHS.startLoc() < RHS.startLoc(); - }); - - Segments = SegmentBuilder().buildSegments(Regions); - } - - return Segments; -} diff --git a/llvm/tools/llvm-cov/SourceCoverageDataManager.h b/llvm/tools/llvm-cov/SourceCoverageDataManager.h deleted file mode 100644 index eec175222b4..00000000000 --- a/llvm/tools/llvm-cov/SourceCoverageDataManager.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- SourceCoverageDataManager.h - Manager for source file coverage data-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class separates and merges mapping regions for a specific source file. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_COV_SOURCECOVERAGEDATAMANAGER_H -#define LLVM_COV_SOURCECOVERAGEDATAMANAGER_H - -#include "llvm/ProfileData/CoverageMapping.h" -#include <vector> - -namespace llvm { - -struct CoverageSegment { - unsigned Line; - unsigned Col; - bool IsRegionEntry; - uint64_t Count; - bool HasCount; - - CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) - : Line(Line), Col(Col), IsRegionEntry(IsRegionEntry), - Count(0), HasCount(false) {} - void setCount(uint64_t NewCount) { - Count = NewCount; - HasCount = true; - } -}; - -/// \brief Partions mapping regions by their kind and sums -/// the execution counts of the regions that start at the same location. -class SourceCoverageDataManager { - std::vector<coverage::CountedRegion> Regions; - std::vector<CoverageSegment> Segments; - -public: - void insert(const coverage::CountedRegion &CR); - - /// \brief Return a sequence of non-overlapping coverage segments. - ArrayRef<CoverageSegment> getCoverageSegments(); -}; - -} // namespace llvm - -#endif // LLVM_COV_SOURCECOVERAGEDATAMANAGER_H diff --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp index 3be54f828da..015099c7d02 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp @@ -18,11 +18,11 @@ using namespace llvm; -void SourceCoverageView::renderLine(raw_ostream &OS, StringRef Line, - int64_t LineNumber, - const CoverageSegment *WrappedSegment, - ArrayRef<const CoverageSegment *> Segments, - unsigned ExpansionCol) { +void SourceCoverageView::renderLine( + raw_ostream &OS, StringRef Line, int64_t LineNumber, + const coverage::CoverageSegment *WrappedSegment, + ArrayRef<const coverage::CoverageSegment *> Segments, + unsigned ExpansionCol) { Optional<raw_ostream::Colors> Highlight; SmallVector<std::pair<unsigned, unsigned>, 2> HighlightedRanges; @@ -110,7 +110,7 @@ void SourceCoverageView::renderLineNumberColumn(raw_ostream &OS, } void SourceCoverageView::renderRegionMarkers( - raw_ostream &OS, ArrayRef<const CoverageSegment *> Segments) { + raw_ostream &OS, ArrayRef<const coverage::CoverageSegment *> Segments) { SmallString<32> Buffer; raw_svector_ostream BufferOS(Buffer); @@ -158,14 +158,12 @@ void SourceCoverageView::render(raw_ostream &OS, bool WholeFile, auto EndISV = InstantiationSubViews.end(); // Get the coverage information for the file. - auto CoverageSegments = RegionManager->getCoverageSegments(); - assert(CoverageSegments.size() && "View with no coverage?"); - auto NextSegment = CoverageSegments.begin(); - auto EndSegment = CoverageSegments.end(); + auto NextSegment = CoverageInfo.begin(); + auto EndSegment = CoverageInfo.end(); unsigned FirstLine = NextSegment != EndSegment ? NextSegment->Line : 0; - const CoverageSegment *WrappedSegment = nullptr; - SmallVector<const CoverageSegment *, 8> LineSegments; + const coverage::CoverageSegment *WrappedSegment = nullptr; + SmallVector<const coverage::CoverageSegment *, 8> LineSegments; for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI) { // If we aren't rendering the whole file, we need to filter out the prologue // and epilogue. diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h index 54a11d8c51c..d92a7486d9d 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.h +++ b/llvm/tools/llvm-cov/SourceCoverageView.h @@ -15,7 +15,6 @@ #define LLVM_COV_SOURCECOVERAGEVIEW_H #include "CoverageViewOptions.h" -#include "SourceCoverageDataManager.h" #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/Support/MemoryBuffer.h" #include <vector> @@ -105,14 +104,14 @@ private: const MemoryBuffer &File; const CoverageViewOptions &Options; - std::unique_ptr<SourceCoverageDataManager> RegionManager; + coverage::CoverageData CoverageInfo; std::vector<ExpansionView> ExpansionSubViews; std::vector<InstantiationView> InstantiationSubViews; /// \brief Render a source line with highlighting. void renderLine(raw_ostream &OS, StringRef Line, int64_t LineNumber, - const CoverageSegment *WrappedSegment, - ArrayRef<const CoverageSegment *> Segments, + const coverage::CoverageSegment *WrappedSegment, + ArrayRef<const coverage::CoverageSegment *> Segments, unsigned ExpansionCol); void renderIndent(raw_ostream &OS, unsigned Level); @@ -126,16 +125,18 @@ private: void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo); /// \brief Render all the region's execution counts on a line. - void renderRegionMarkers(raw_ostream &OS, - ArrayRef<const CoverageSegment *> Segments); + void + renderRegionMarkers(raw_ostream &OS, + ArrayRef<const coverage::CoverageSegment *> Segments); static const unsigned LineCoverageColumnWidth = 7; static const unsigned LineNumberColumnWidth = 5; public: SourceCoverageView(const MemoryBuffer &File, - const CoverageViewOptions &Options) - : File(File), Options(Options) {} + const CoverageViewOptions &Options, + coverage::CoverageData &&CoverageInfo) + : File(File), Options(Options), CoverageInfo(std::move(CoverageInfo)) {} const CoverageViewOptions &getOptions() const { return Options; } @@ -154,12 +155,6 @@ public: /// \brief Print the code coverage information for a specific /// portion of a source file to the output stream. void render(raw_ostream &OS, bool WholeFile, unsigned IndentLevel = 0); - - /// \brief Load the coverage information required for rendering - /// from the mapping regions in the data manager. - void load(std::unique_ptr<SourceCoverageDataManager> Data) { - RegionManager = std::move(Data); - } }; } // namespace llvm |