diff options
Diffstat (limited to 'lib/ProfileData/CoverageMapping.cpp')
| -rw-r--r-- | lib/ProfileData/CoverageMapping.cpp | 157 | 
1 files changed, 106 insertions, 51 deletions
diff --git a/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp index 175277755b800..bbac5c26b1ebd 100644 --- a/lib/ProfileData/CoverageMapping.cpp +++ b/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; +}  | 
