//===----------------------------------------------------------------------===//
#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"
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) {
continue;
}
- Coverage->Functions.push_back(Function);
+ Coverage->Functions.push_back(std::move(Function));
}
return std::move(Coverage);
ObjectFileCoverageMappingReader CoverageReader(CounterMappingBuff.get());
if (auto EC = CoverageReader.readHeader())
return EC;
- std::unique_ptr<IndexedInstrProfReader> ProfileReader;
- if (auto EC = IndexedInstrProfReader::create(ProfileFilename, ProfileReader))
+ auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
+ if (auto EC = ProfileReaderOrErr.getError())
return EC;
+ auto ProfileReader = std::move(ProfileReaderOrErr.get());
return load(CoverageReader, *ProfileReader);
}
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 (PrevRegion && PrevRegion->startLoc() == Region.startLoc() &&
+ PrevRegion->endLoc() == Region.endLoc()) {
if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion)
Segments.back().addCount(Region.ExecutionCount);
} else {
ActiveRegions.push_back(&Region);
startSegment(Region);
}
+ PrevRegion = &Region;
}
// Pop any regions that are left in the stack.
while (!ActiveRegions.empty())
};
}
-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)
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();
+ return I != -1 ? I : None;
}
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();
+ return I != -1 ? I : None;
}
/// Sort a nested sequence of regions from a single file.
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);
}
sortNestedRegions(Regions.begin(), Regions.end());
+ DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
FileCoverage.Segments = SegmentBuilder().buildSegments(Regions);
return FileCoverage;
}
sortNestedRegions(Regions.begin(), Regions.end());
+ DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
return FunctionCoverage;
}
sortNestedRegions(Regions.begin(), Regions.end());
+ DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
+ << "\n");
ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
return ExpansionCoverage;