diff options
Diffstat (limited to 'contrib/llvm/lib/ProfileData/CoverageMapping.cpp')
-rw-r--r-- | contrib/llvm/lib/ProfileData/CoverageMapping.cpp | 157 |
1 files changed, 106 insertions, 51 deletions
diff --git a/contrib/llvm/lib/ProfileData/CoverageMapping.cpp b/contrib/llvm/lib/ProfileData/CoverageMapping.cpp index 1752777..bbac5c2 100644 --- a/contrib/llvm/lib/ProfileData/CoverageMapping.cpp +++ b/contrib/llvm/lib/ProfileData/CoverageMapping.cpp @@ -15,11 +15,14 @@ #include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ProfileData/CoverageMappingReader.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace coverage; @@ -177,32 +180,47 @@ void FunctionRecordIterator::skipOtherFiles() { *this = FunctionRecordIterator(); } +/// Get the function name from the record, removing the filename prefix if +/// necessary. +static StringRef getFuncNameWithoutPrefix(const CoverageMappingRecord &Record) { + StringRef FunctionName = Record.FunctionName; + if (Record.Filenames.empty()) + return FunctionName; + StringRef Filename = sys::path::filename(Record.Filenames[0]); + if (FunctionName.startswith(Filename)) + FunctionName = FunctionName.drop_front(Filename.size() + 1); + return FunctionName; +} + ErrorOr<std::unique_ptr<CoverageMapping>> -CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader, +CoverageMapping::load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader) { auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); std::vector<uint64_t> Counts; for (const auto &Record : CoverageReader) { + CounterMappingContext Ctx(Record.Expressions); + Counts.clear(); if (std::error_code EC = ProfileReader.getFunctionCounts( Record.FunctionName, Record.FunctionHash, Counts)) { - if (EC != instrprof_error::hash_mismatch && - EC != instrprof_error::unknown_function) + if (EC == instrprof_error::hash_mismatch) { + Coverage->MismatchedFunctionCount++; + continue; + } else if (EC != instrprof_error::unknown_function) return EC; - Coverage->MismatchedFunctionCount++; - continue; + Counts.assign(Record.MappingRegions.size(), 0); } + Ctx.setCounts(Counts); + + assert(!Record.MappingRegions.empty() && "Function has no regions"); - assert(Counts.size() != 0 && "Function's counts are empty"); - FunctionRecord Function(Record.FunctionName, Record.Filenames, - Counts.front()); - CounterMappingContext Ctx(Record.Expressions, Counts); + FunctionRecord Function(getFuncNameWithoutPrefix(Record), Record.Filenames); for (const auto &Region : Record.MappingRegions) { ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); if (!ExecutionCount) break; - Function.CountedRegions.push_back(CountedRegion(Region, *ExecutionCount)); + Function.pushRegion(Region, *ExecutionCount); } if (Function.CountedRegions.size() != Record.MappingRegions.size()) { Coverage->MismatchedFunctionCount++; @@ -216,17 +234,21 @@ CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader, } ErrorOr<std::unique_ptr<CoverageMapping>> -CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename) { +CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename, + Triple::ArchType Arch) { auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename); - if (auto EC = CounterMappingBuff.getError()) + if (std::error_code EC = CounterMappingBuff.getError()) return EC; - ObjectFileCoverageMappingReader CoverageReader(CounterMappingBuff.get()); - if (auto EC = CoverageReader.readHeader()) + auto CoverageReaderOrErr = + BinaryCoverageReader::create(CounterMappingBuff.get(), Arch); + if (std::error_code EC = CoverageReaderOrErr.getError()) return EC; - std::unique_ptr<IndexedInstrProfReader> ProfileReader; - if (auto EC = IndexedInstrProfReader::create(ProfileFilename, ProfileReader)) + auto CoverageReader = std::move(CoverageReaderOrErr.get()); + auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename); + if (auto EC = ProfileReaderOrErr.getError()) return EC; - return load(CoverageReader, *ProfileReader); + auto ProfileReader = std::move(ProfileReaderOrErr.get()); + return load(*CoverageReader, *ProfileReader); } namespace { @@ -304,20 +326,22 @@ class SegmentBuilder { public: /// Build a list of CoverageSegments from a sorted list of Regions. std::vector<CoverageSegment> buildSegments(ArrayRef<CountedRegion> Regions) { + const CountedRegion *PrevRegion = nullptr; for (const auto &Region : Regions) { // Pop any regions that end before this one starts. while (!ActiveRegions.empty() && ActiveRegions.back()->endLoc() <= Region.startLoc()) popRegion(); - if (Segments.size() && Segments.back().Line == Region.LineStart && - Segments.back().Col == Region.ColumnStart) { - if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) + if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() && + PrevRegion->endLoc() == Region.endLoc()) { + if (Region.Kind == coverage::CounterMappingRegion::CodeRegion) Segments.back().addCount(Region.ExecutionCount); } else { // Add this region to the stack. ActiveRegions.push_back(&Region); startSegment(Region); } + PrevRegion = &Region; } // Pop any regions that are left in the stack. while (!ActiveRegions.empty()) @@ -330,50 +354,47 @@ public: std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { std::vector<StringRef> Filenames; for (const auto &Function : getCoveredFunctions()) - for (const auto &Filename : Function.Filenames) - Filenames.push_back(Filename); + Filenames.insert(Filenames.end(), Function.Filenames.begin(), + Function.Filenames.end()); std::sort(Filenames.begin(), Filenames.end()); auto Last = std::unique(Filenames.begin(), Filenames.end()); Filenames.erase(Last, Filenames.end()); return Filenames; } -static Optional<unsigned> findMainViewFileID(StringRef SourceFile, - const FunctionRecord &Function) { - llvm::SmallVector<bool, 8> IsExpandedFile(Function.Filenames.size(), false); - llvm::SmallVector<bool, 8> FilenameEquivalence(Function.Filenames.size(), - false); +static SmallBitVector gatherFileIDs(StringRef SourceFile, + const FunctionRecord &Function) { + SmallBitVector FilenameEquivalence(Function.Filenames.size(), false); for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) if (SourceFile == Function.Filenames[I]) FilenameEquivalence[I] = true; + return FilenameEquivalence; +} + +static Optional<unsigned> findMainViewFileID(StringRef SourceFile, + const FunctionRecord &Function) { + SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); + SmallBitVector FilenameEquivalence = gatherFileIDs(SourceFile, Function); 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]) - return I; - return None; + IsNotExpandedFile[CR.ExpandedFileID] = false; + IsNotExpandedFile &= FilenameEquivalence; + int I = IsNotExpandedFile.find_first(); + if (I == -1) + return None; + return I; } static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) { - llvm::SmallVector<bool, 8> IsExpandedFile(Function.Filenames.size(), false); + SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); 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]) - return I; - return None; -} - -static SmallSet<unsigned, 8> gatherFileIDs(StringRef SourceFile, - const FunctionRecord &Function) { - SmallSet<unsigned, 8> IDs; - for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) - if (SourceFile == Function.Filenames[I]) - IDs.insert(I); - return IDs; + IsNotExpandedFile[CR.ExpandedFileID] = false; + int I = IsNotExpandedFile.find_first(); + if (I == -1) + return None; + return I; } /// Sort a nested sequence of regions from a single file. @@ -401,7 +422,7 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) { continue; auto FileIDs = gatherFileIDs(Filename, Function); for (const auto &CR : Function.CountedRegions) - if (FileIDs.count(CR.FileID)) { + if (FileIDs.test(CR.FileID)) { Regions.push_back(CR); if (isExpansion(CR, *MainFileID)) FileCoverage.Expansions.emplace_back(CR, Function); @@ -409,6 +430,7 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) { } sortNestedRegions(Regions.begin(), Regions.end()); + DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n"); FileCoverage.Segments = SegmentBuilder().buildSegments(Regions); return FileCoverage; @@ -428,8 +450,8 @@ CoverageMapping::getInstantiations(StringRef Filename) { for (const auto &InstantiationSet : InstantiationSetCollector) { if (InstantiationSet.second.size() < 2) continue; - for (auto Function : InstantiationSet.second) - Result.push_back(Function); + Result.insert(Result.end(), InstantiationSet.second.begin(), + InstantiationSet.second.end()); } return Result; } @@ -450,6 +472,7 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) { } sortNestedRegions(Regions.begin(), Regions.end()); + DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n"); FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions); return FunctionCoverage; @@ -468,7 +491,39 @@ CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) { } sortNestedRegions(Regions.begin(), Regions.end()); + DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID + << "\n"); ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions); return ExpansionCoverage; } + +namespace { +class CoverageMappingErrorCategoryType : public std::error_category { + const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; } + std::string message(int IE) const override { + auto E = static_cast<coveragemap_error>(IE); + switch (E) { + case coveragemap_error::success: + return "Success"; + case coveragemap_error::eof: + return "End of File"; + case coveragemap_error::no_data_found: + return "No coverage data found"; + case coveragemap_error::unsupported_version: + return "Unsupported coverage format version"; + case coveragemap_error::truncated: + return "Truncated coverage data"; + case coveragemap_error::malformed: + return "Malformed coverage data"; + } + llvm_unreachable("A value of coveragemap_error has no message."); + } +}; +} + +static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory; + +const std::error_category &llvm::coveragemap_category() { + return *ErrorCategory; +} |