CoverageMapping.cpp revision 321369
1321369Sdim//===- CoverageMapping.cpp - Code coverage mapping support ----------------===// 2303231Sdim// 3303231Sdim// The LLVM Compiler Infrastructure 4303231Sdim// 5303231Sdim// This file is distributed under the University of Illinois Open Source 6303231Sdim// License. See LICENSE.TXT for details. 7303231Sdim// 8303231Sdim//===----------------------------------------------------------------------===// 9303231Sdim// 10303231Sdim// This file contains support for clang's and llvm's instrumentation based 11303231Sdim// code coverage. 12303231Sdim// 13303231Sdim//===----------------------------------------------------------------------===// 14303231Sdim 15303231Sdim#include "llvm/ProfileData/Coverage/CoverageMapping.h" 16321369Sdim#include "llvm/ADT/ArrayRef.h" 17303231Sdim#include "llvm/ADT/DenseMap.h" 18321369Sdim#include "llvm/ADT/None.h" 19303231Sdim#include "llvm/ADT/Optional.h" 20303231Sdim#include "llvm/ADT/SmallBitVector.h" 21321369Sdim#include "llvm/ADT/SmallVector.h" 22321369Sdim#include "llvm/ADT/StringRef.h" 23303231Sdim#include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 24303231Sdim#include "llvm/ProfileData/InstrProfReader.h" 25303231Sdim#include "llvm/Support/Debug.h" 26303231Sdim#include "llvm/Support/Errc.h" 27321369Sdim#include "llvm/Support/Error.h" 28303231Sdim#include "llvm/Support/ErrorHandling.h" 29303231Sdim#include "llvm/Support/ManagedStatic.h" 30321369Sdim#include "llvm/Support/MemoryBuffer.h" 31303231Sdim#include "llvm/Support/raw_ostream.h" 32321369Sdim#include <algorithm> 33321369Sdim#include <cassert> 34321369Sdim#include <cstdint> 35321369Sdim#include <iterator> 36321369Sdim#include <memory> 37321369Sdim#include <string> 38321369Sdim#include <system_error> 39321369Sdim#include <utility> 40321369Sdim#include <vector> 41303231Sdim 42303231Sdimusing namespace llvm; 43303231Sdimusing namespace coverage; 44303231Sdim 45303231Sdim#define DEBUG_TYPE "coverage-mapping" 46303231Sdim 47303231SdimCounter CounterExpressionBuilder::get(const CounterExpression &E) { 48303231Sdim auto It = ExpressionIndices.find(E); 49303231Sdim if (It != ExpressionIndices.end()) 50303231Sdim return Counter::getExpression(It->second); 51303231Sdim unsigned I = Expressions.size(); 52303231Sdim Expressions.push_back(E); 53303231Sdim ExpressionIndices[E] = I; 54303231Sdim return Counter::getExpression(I); 55303231Sdim} 56303231Sdim 57321369Sdimvoid CounterExpressionBuilder::extractTerms(Counter C, int Factor, 58321369Sdim SmallVectorImpl<Term> &Terms) { 59303231Sdim switch (C.getKind()) { 60303231Sdim case Counter::Zero: 61303231Sdim break; 62303231Sdim case Counter::CounterValueReference: 63321369Sdim Terms.emplace_back(C.getCounterID(), Factor); 64303231Sdim break; 65303231Sdim case Counter::Expression: 66303231Sdim const auto &E = Expressions[C.getExpressionID()]; 67321369Sdim extractTerms(E.LHS, Factor, Terms); 68321369Sdim extractTerms( 69321369Sdim E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms); 70303231Sdim break; 71303231Sdim } 72303231Sdim} 73303231Sdim 74303231SdimCounter CounterExpressionBuilder::simplify(Counter ExpressionTree) { 75303231Sdim // Gather constant terms. 76321369Sdim SmallVector<Term, 32> Terms; 77303231Sdim extractTerms(ExpressionTree, +1, Terms); 78303231Sdim 79303231Sdim // If there are no terms, this is just a zero. The algorithm below assumes at 80303231Sdim // least one term. 81303231Sdim if (Terms.size() == 0) 82303231Sdim return Counter::getZero(); 83303231Sdim 84303231Sdim // Group the terms by counter ID. 85321369Sdim std::sort(Terms.begin(), Terms.end(), [](const Term &LHS, const Term &RHS) { 86321369Sdim return LHS.CounterID < RHS.CounterID; 87303231Sdim }); 88303231Sdim 89303231Sdim // Combine terms by counter ID to eliminate counters that sum to zero. 90303231Sdim auto Prev = Terms.begin(); 91303231Sdim for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) { 92321369Sdim if (I->CounterID == Prev->CounterID) { 93321369Sdim Prev->Factor += I->Factor; 94303231Sdim continue; 95303231Sdim } 96303231Sdim ++Prev; 97303231Sdim *Prev = *I; 98303231Sdim } 99303231Sdim Terms.erase(++Prev, Terms.end()); 100303231Sdim 101303231Sdim Counter C; 102303231Sdim // Create additions. We do this before subtractions to avoid constructs like 103303231Sdim // ((0 - X) + Y), as opposed to (Y - X). 104321369Sdim for (auto T : Terms) { 105321369Sdim if (T.Factor <= 0) 106303231Sdim continue; 107321369Sdim for (int I = 0; I < T.Factor; ++I) 108303231Sdim if (C.isZero()) 109321369Sdim C = Counter::getCounter(T.CounterID); 110303231Sdim else 111303231Sdim C = get(CounterExpression(CounterExpression::Add, C, 112321369Sdim Counter::getCounter(T.CounterID))); 113303231Sdim } 114303231Sdim 115303231Sdim // Create subtractions. 116321369Sdim for (auto T : Terms) { 117321369Sdim if (T.Factor >= 0) 118303231Sdim continue; 119321369Sdim for (int I = 0; I < -T.Factor; ++I) 120303231Sdim C = get(CounterExpression(CounterExpression::Subtract, C, 121321369Sdim Counter::getCounter(T.CounterID))); 122303231Sdim } 123303231Sdim return C; 124303231Sdim} 125303231Sdim 126303231SdimCounter CounterExpressionBuilder::add(Counter LHS, Counter RHS) { 127303231Sdim return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS))); 128303231Sdim} 129303231Sdim 130303231SdimCounter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) { 131303231Sdim return simplify( 132303231Sdim get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); 133303231Sdim} 134303231Sdim 135321369Sdimvoid CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const { 136303231Sdim switch (C.getKind()) { 137303231Sdim case Counter::Zero: 138303231Sdim OS << '0'; 139303231Sdim return; 140303231Sdim case Counter::CounterValueReference: 141303231Sdim OS << '#' << C.getCounterID(); 142303231Sdim break; 143303231Sdim case Counter::Expression: { 144303231Sdim if (C.getExpressionID() >= Expressions.size()) 145303231Sdim return; 146303231Sdim const auto &E = Expressions[C.getExpressionID()]; 147303231Sdim OS << '('; 148303231Sdim dump(E.LHS, OS); 149303231Sdim OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); 150303231Sdim dump(E.RHS, OS); 151303231Sdim OS << ')'; 152303231Sdim break; 153303231Sdim } 154303231Sdim } 155303231Sdim if (CounterValues.empty()) 156303231Sdim return; 157303231Sdim Expected<int64_t> Value = evaluate(C); 158303231Sdim if (auto E = Value.takeError()) { 159321369Sdim consumeError(std::move(E)); 160303231Sdim return; 161303231Sdim } 162303231Sdim OS << '[' << *Value << ']'; 163303231Sdim} 164303231Sdim 165303231SdimExpected<int64_t> CounterMappingContext::evaluate(const Counter &C) const { 166303231Sdim switch (C.getKind()) { 167303231Sdim case Counter::Zero: 168303231Sdim return 0; 169303231Sdim case Counter::CounterValueReference: 170303231Sdim if (C.getCounterID() >= CounterValues.size()) 171303231Sdim return errorCodeToError(errc::argument_out_of_domain); 172303231Sdim return CounterValues[C.getCounterID()]; 173303231Sdim case Counter::Expression: { 174303231Sdim if (C.getExpressionID() >= Expressions.size()) 175303231Sdim return errorCodeToError(errc::argument_out_of_domain); 176303231Sdim const auto &E = Expressions[C.getExpressionID()]; 177303231Sdim Expected<int64_t> LHS = evaluate(E.LHS); 178303231Sdim if (!LHS) 179303231Sdim return LHS; 180303231Sdim Expected<int64_t> RHS = evaluate(E.RHS); 181303231Sdim if (!RHS) 182303231Sdim return RHS; 183303231Sdim return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS; 184303231Sdim } 185303231Sdim } 186303231Sdim llvm_unreachable("Unhandled CounterKind"); 187303231Sdim} 188303231Sdim 189303231Sdimvoid FunctionRecordIterator::skipOtherFiles() { 190303231Sdim while (Current != Records.end() && !Filename.empty() && 191303231Sdim Filename != Current->Filenames[0]) 192303231Sdim ++Current; 193303231Sdim if (Current == Records.end()) 194303231Sdim *this = FunctionRecordIterator(); 195303231Sdim} 196303231Sdim 197314564SdimError CoverageMapping::loadFunctionRecord( 198314564Sdim const CoverageMappingRecord &Record, 199314564Sdim IndexedInstrProfReader &ProfileReader) { 200314564Sdim StringRef OrigFuncName = Record.FunctionName; 201321369Sdim if (OrigFuncName.empty()) 202321369Sdim return make_error<CoverageMapError>(coveragemap_error::malformed); 203321369Sdim 204314564Sdim if (Record.Filenames.empty()) 205314564Sdim OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName); 206314564Sdim else 207314564Sdim OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]); 208314564Sdim 209314564Sdim // Don't load records for functions we've already seen. 210314564Sdim if (!FunctionNames.insert(OrigFuncName).second) 211314564Sdim return Error::success(); 212314564Sdim 213314564Sdim CounterMappingContext Ctx(Record.Expressions); 214314564Sdim 215314564Sdim std::vector<uint64_t> Counts; 216314564Sdim if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName, 217314564Sdim Record.FunctionHash, Counts)) { 218314564Sdim instrprof_error IPE = InstrProfError::take(std::move(E)); 219314564Sdim if (IPE == instrprof_error::hash_mismatch) { 220314564Sdim MismatchedFunctionCount++; 221314564Sdim return Error::success(); 222314564Sdim } else if (IPE != instrprof_error::unknown_function) 223314564Sdim return make_error<InstrProfError>(IPE); 224314564Sdim Counts.assign(Record.MappingRegions.size(), 0); 225314564Sdim } 226314564Sdim Ctx.setCounts(Counts); 227314564Sdim 228314564Sdim assert(!Record.MappingRegions.empty() && "Function has no regions"); 229314564Sdim 230314564Sdim FunctionRecord Function(OrigFuncName, Record.Filenames); 231314564Sdim for (const auto &Region : Record.MappingRegions) { 232314564Sdim Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); 233314564Sdim if (auto E = ExecutionCount.takeError()) { 234321369Sdim consumeError(std::move(E)); 235314564Sdim return Error::success(); 236314564Sdim } 237314564Sdim Function.pushRegion(Region, *ExecutionCount); 238314564Sdim } 239314564Sdim if (Function.CountedRegions.size() != Record.MappingRegions.size()) { 240314564Sdim MismatchedFunctionCount++; 241314564Sdim return Error::success(); 242314564Sdim } 243314564Sdim 244314564Sdim Functions.push_back(std::move(Function)); 245314564Sdim return Error::success(); 246314564Sdim} 247314564Sdim 248314564SdimExpected<std::unique_ptr<CoverageMapping>> CoverageMapping::load( 249314564Sdim ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 250314564Sdim IndexedInstrProfReader &ProfileReader) { 251314564Sdim auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); 252303231Sdim 253314564Sdim for (const auto &CoverageReader : CoverageReaders) 254314564Sdim for (const auto &Record : *CoverageReader) 255314564Sdim if (Error E = Coverage->loadFunctionRecord(Record, ProfileReader)) 256314564Sdim return std::move(E); 257303231Sdim 258303231Sdim return std::move(Coverage); 259303231Sdim} 260303231Sdim 261303231SdimExpected<std::unique_ptr<CoverageMapping>> 262314564SdimCoverageMapping::load(ArrayRef<StringRef> ObjectFilenames, 263314564Sdim StringRef ProfileFilename, StringRef Arch) { 264303231Sdim auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename); 265303231Sdim if (Error E = ProfileReaderOrErr.takeError()) 266303231Sdim return std::move(E); 267303231Sdim auto ProfileReader = std::move(ProfileReaderOrErr.get()); 268314564Sdim 269314564Sdim SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers; 270314564Sdim SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers; 271314564Sdim for (StringRef ObjectFilename : ObjectFilenames) { 272314564Sdim auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(ObjectFilename); 273314564Sdim if (std::error_code EC = CovMappingBufOrErr.getError()) 274314564Sdim return errorCodeToError(EC); 275314564Sdim auto CoverageReaderOrErr = 276314564Sdim BinaryCoverageReader::create(CovMappingBufOrErr.get(), Arch); 277314564Sdim if (Error E = CoverageReaderOrErr.takeError()) 278314564Sdim return std::move(E); 279314564Sdim Readers.push_back(std::move(CoverageReaderOrErr.get())); 280314564Sdim Buffers.push_back(std::move(CovMappingBufOrErr.get())); 281314564Sdim } 282314564Sdim return load(Readers, *ProfileReader); 283303231Sdim} 284303231Sdim 285303231Sdimnamespace { 286321369Sdim 287303231Sdim/// \brief Distributes functions into instantiation sets. 288303231Sdim/// 289303231Sdim/// An instantiation set is a collection of functions that have the same source 290303231Sdim/// code, ie, template functions specializations. 291303231Sdimclass FunctionInstantiationSetCollector { 292321369Sdim using MapT = DenseMap<std::pair<unsigned, unsigned>, 293321369Sdim std::vector<const FunctionRecord *>>; 294303231Sdim MapT InstantiatedFunctions; 295303231Sdim 296303231Sdimpublic: 297303231Sdim void insert(const FunctionRecord &Function, unsigned FileID) { 298303231Sdim auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end(); 299303231Sdim while (I != E && I->FileID != FileID) 300303231Sdim ++I; 301303231Sdim assert(I != E && "function does not cover the given file"); 302303231Sdim auto &Functions = InstantiatedFunctions[I->startLoc()]; 303303231Sdim Functions.push_back(&Function); 304303231Sdim } 305303231Sdim 306303231Sdim MapT::iterator begin() { return InstantiatedFunctions.begin(); } 307303231Sdim MapT::iterator end() { return InstantiatedFunctions.end(); } 308303231Sdim}; 309303231Sdim 310303231Sdimclass SegmentBuilder { 311303231Sdim std::vector<CoverageSegment> &Segments; 312303231Sdim SmallVector<const CountedRegion *, 8> ActiveRegions; 313303231Sdim 314303231Sdim SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {} 315303231Sdim 316303231Sdim /// Start a segment with no count specified. 317303231Sdim void startSegment(unsigned Line, unsigned Col) { 318303231Sdim DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n"); 319303231Sdim Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false); 320303231Sdim } 321303231Sdim 322303231Sdim /// Start a segment with the given Region's count. 323303231Sdim void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry, 324303231Sdim const CountedRegion &Region) { 325303231Sdim // Avoid creating empty regions. 326303231Sdim if (!Segments.empty() && Segments.back().Line == Line && 327303231Sdim Segments.back().Col == Col) 328303231Sdim Segments.pop_back(); 329303231Sdim DEBUG(dbgs() << "Segment at " << Line << ":" << Col); 330303231Sdim // Set this region's count. 331321369Sdim if (Region.Kind != CounterMappingRegion::SkippedRegion) { 332303231Sdim DEBUG(dbgs() << " with count " << Region.ExecutionCount); 333303231Sdim Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry); 334303231Sdim } else 335303231Sdim Segments.emplace_back(Line, Col, IsRegionEntry); 336303231Sdim DEBUG(dbgs() << "\n"); 337303231Sdim } 338303231Sdim 339303231Sdim /// Start a segment for the given region. 340303231Sdim void startSegment(const CountedRegion &Region) { 341303231Sdim startSegment(Region.LineStart, Region.ColumnStart, true, Region); 342303231Sdim } 343303231Sdim 344303231Sdim /// Pop the top region off of the active stack, starting a new segment with 345303231Sdim /// the containing Region's count. 346303231Sdim void popRegion() { 347303231Sdim const CountedRegion *Active = ActiveRegions.back(); 348303231Sdim unsigned Line = Active->LineEnd, Col = Active->ColumnEnd; 349303231Sdim ActiveRegions.pop_back(); 350303231Sdim if (ActiveRegions.empty()) 351303231Sdim startSegment(Line, Col); 352303231Sdim else 353303231Sdim startSegment(Line, Col, false, *ActiveRegions.back()); 354303231Sdim } 355303231Sdim 356303231Sdim void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) { 357303231Sdim for (const auto &Region : Regions) { 358303231Sdim // Pop any regions that end before this one starts. 359303231Sdim while (!ActiveRegions.empty() && 360303231Sdim ActiveRegions.back()->endLoc() <= Region.startLoc()) 361303231Sdim popRegion(); 362303231Sdim // Add this region to the stack. 363303231Sdim ActiveRegions.push_back(&Region); 364303231Sdim startSegment(Region); 365303231Sdim } 366303231Sdim // Pop any regions that are left in the stack. 367303231Sdim while (!ActiveRegions.empty()) 368303231Sdim popRegion(); 369303231Sdim } 370303231Sdim 371303231Sdim /// Sort a nested sequence of regions from a single file. 372303231Sdim static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) { 373303231Sdim std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS, 374303231Sdim const CountedRegion &RHS) { 375303231Sdim if (LHS.startLoc() != RHS.startLoc()) 376303231Sdim return LHS.startLoc() < RHS.startLoc(); 377303231Sdim if (LHS.endLoc() != RHS.endLoc()) 378303231Sdim // When LHS completely contains RHS, we sort LHS first. 379303231Sdim return RHS.endLoc() < LHS.endLoc(); 380303231Sdim // If LHS and RHS cover the same area, we need to sort them according 381303231Sdim // to their kinds so that the most suitable region will become "active" 382303231Sdim // in combineRegions(). Because we accumulate counter values only from 383303231Sdim // regions of the same kind as the first region of the area, prefer 384303231Sdim // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion. 385321369Sdim static_assert(CounterMappingRegion::CodeRegion < 386321369Sdim CounterMappingRegion::ExpansionRegion && 387321369Sdim CounterMappingRegion::ExpansionRegion < 388321369Sdim CounterMappingRegion::SkippedRegion, 389303231Sdim "Unexpected order of region kind values"); 390303231Sdim return LHS.Kind < RHS.Kind; 391303231Sdim }); 392303231Sdim } 393303231Sdim 394303231Sdim /// Combine counts of regions which cover the same area. 395303231Sdim static ArrayRef<CountedRegion> 396303231Sdim combineRegions(MutableArrayRef<CountedRegion> Regions) { 397303231Sdim if (Regions.empty()) 398303231Sdim return Regions; 399303231Sdim auto Active = Regions.begin(); 400303231Sdim auto End = Regions.end(); 401303231Sdim for (auto I = Regions.begin() + 1; I != End; ++I) { 402303231Sdim if (Active->startLoc() != I->startLoc() || 403303231Sdim Active->endLoc() != I->endLoc()) { 404303231Sdim // Shift to the next region. 405303231Sdim ++Active; 406303231Sdim if (Active != I) 407303231Sdim *Active = *I; 408303231Sdim continue; 409303231Sdim } 410303231Sdim // Merge duplicate region. 411303231Sdim // If CodeRegions and ExpansionRegions cover the same area, it's probably 412303231Sdim // a macro which is fully expanded to another macro. In that case, we need 413303231Sdim // to accumulate counts only from CodeRegions, or else the area will be 414303231Sdim // counted twice. 415303231Sdim // On the other hand, a macro may have a nested macro in its body. If the 416303231Sdim // outer macro is used several times, the ExpansionRegion for the nested 417303231Sdim // macro will also be added several times. These ExpansionRegions cover 418303231Sdim // the same source locations and have to be combined to reach the correct 419303231Sdim // value for that area. 420303231Sdim // We add counts of the regions of the same kind as the active region 421303231Sdim // to handle the both situations. 422303231Sdim if (I->Kind == Active->Kind) 423303231Sdim Active->ExecutionCount += I->ExecutionCount; 424303231Sdim } 425303231Sdim return Regions.drop_back(std::distance(++Active, End)); 426303231Sdim } 427303231Sdim 428303231Sdimpublic: 429303231Sdim /// Build a list of CoverageSegments from a list of Regions. 430303231Sdim static std::vector<CoverageSegment> 431303231Sdim buildSegments(MutableArrayRef<CountedRegion> Regions) { 432303231Sdim std::vector<CoverageSegment> Segments; 433303231Sdim SegmentBuilder Builder(Segments); 434303231Sdim 435303231Sdim sortNestedRegions(Regions); 436303231Sdim ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions); 437303231Sdim 438303231Sdim Builder.buildSegmentsImpl(CombinedRegions); 439303231Sdim return Segments; 440303231Sdim } 441303231Sdim}; 442303231Sdim 443321369Sdim} // end anonymous namespace 444321369Sdim 445303231Sdimstd::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { 446303231Sdim std::vector<StringRef> Filenames; 447303231Sdim for (const auto &Function : getCoveredFunctions()) 448303231Sdim Filenames.insert(Filenames.end(), Function.Filenames.begin(), 449303231Sdim Function.Filenames.end()); 450303231Sdim std::sort(Filenames.begin(), Filenames.end()); 451303231Sdim auto Last = std::unique(Filenames.begin(), Filenames.end()); 452303231Sdim Filenames.erase(Last, Filenames.end()); 453303231Sdim return Filenames; 454303231Sdim} 455303231Sdim 456303231Sdimstatic SmallBitVector gatherFileIDs(StringRef SourceFile, 457303231Sdim const FunctionRecord &Function) { 458303231Sdim SmallBitVector FilenameEquivalence(Function.Filenames.size(), false); 459303231Sdim for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) 460303231Sdim if (SourceFile == Function.Filenames[I]) 461303231Sdim FilenameEquivalence[I] = true; 462303231Sdim return FilenameEquivalence; 463303231Sdim} 464303231Sdim 465303231Sdim/// Return the ID of the file where the definition of the function is located. 466303231Sdimstatic Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) { 467303231Sdim SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); 468303231Sdim for (const auto &CR : Function.CountedRegions) 469303231Sdim if (CR.Kind == CounterMappingRegion::ExpansionRegion) 470303231Sdim IsNotExpandedFile[CR.ExpandedFileID] = false; 471303231Sdim int I = IsNotExpandedFile.find_first(); 472303231Sdim if (I == -1) 473303231Sdim return None; 474303231Sdim return I; 475303231Sdim} 476303231Sdim 477303231Sdim/// Check if SourceFile is the file that contains the definition of 478303231Sdim/// the Function. Return the ID of the file in that case or None otherwise. 479303231Sdimstatic Optional<unsigned> findMainViewFileID(StringRef SourceFile, 480303231Sdim const FunctionRecord &Function) { 481303231Sdim Optional<unsigned> I = findMainViewFileID(Function); 482303231Sdim if (I && SourceFile == Function.Filenames[*I]) 483303231Sdim return I; 484303231Sdim return None; 485303231Sdim} 486303231Sdim 487303231Sdimstatic bool isExpansion(const CountedRegion &R, unsigned FileID) { 488303231Sdim return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; 489303231Sdim} 490303231Sdim 491303231SdimCoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { 492303231Sdim CoverageData FileCoverage(Filename); 493321369Sdim std::vector<CountedRegion> Regions; 494303231Sdim 495303231Sdim for (const auto &Function : Functions) { 496303231Sdim auto MainFileID = findMainViewFileID(Filename, Function); 497303231Sdim auto FileIDs = gatherFileIDs(Filename, Function); 498303231Sdim for (const auto &CR : Function.CountedRegions) 499303231Sdim if (FileIDs.test(CR.FileID)) { 500303231Sdim Regions.push_back(CR); 501303231Sdim if (MainFileID && isExpansion(CR, *MainFileID)) 502303231Sdim FileCoverage.Expansions.emplace_back(CR, Function); 503303231Sdim } 504303231Sdim } 505303231Sdim 506303231Sdim DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n"); 507303231Sdim FileCoverage.Segments = SegmentBuilder::buildSegments(Regions); 508303231Sdim 509303231Sdim return FileCoverage; 510303231Sdim} 511303231Sdim 512303231Sdimstd::vector<const FunctionRecord *> 513303231SdimCoverageMapping::getInstantiations(StringRef Filename) const { 514303231Sdim FunctionInstantiationSetCollector InstantiationSetCollector; 515303231Sdim for (const auto &Function : Functions) { 516303231Sdim auto MainFileID = findMainViewFileID(Filename, Function); 517303231Sdim if (!MainFileID) 518303231Sdim continue; 519303231Sdim InstantiationSetCollector.insert(Function, *MainFileID); 520303231Sdim } 521303231Sdim 522303231Sdim std::vector<const FunctionRecord *> Result; 523303231Sdim for (const auto &InstantiationSet : InstantiationSetCollector) { 524303231Sdim if (InstantiationSet.second.size() < 2) 525303231Sdim continue; 526303231Sdim Result.insert(Result.end(), InstantiationSet.second.begin(), 527303231Sdim InstantiationSet.second.end()); 528303231Sdim } 529303231Sdim return Result; 530303231Sdim} 531303231Sdim 532303231SdimCoverageData 533303231SdimCoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const { 534303231Sdim auto MainFileID = findMainViewFileID(Function); 535303231Sdim if (!MainFileID) 536303231Sdim return CoverageData(); 537303231Sdim 538303231Sdim CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); 539321369Sdim std::vector<CountedRegion> Regions; 540303231Sdim for (const auto &CR : Function.CountedRegions) 541303231Sdim if (CR.FileID == *MainFileID) { 542303231Sdim Regions.push_back(CR); 543303231Sdim if (isExpansion(CR, *MainFileID)) 544303231Sdim FunctionCoverage.Expansions.emplace_back(CR, Function); 545303231Sdim } 546303231Sdim 547303231Sdim DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n"); 548303231Sdim FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions); 549303231Sdim 550303231Sdim return FunctionCoverage; 551303231Sdim} 552303231Sdim 553303231SdimCoverageData CoverageMapping::getCoverageForExpansion( 554303231Sdim const ExpansionRecord &Expansion) const { 555303231Sdim CoverageData ExpansionCoverage( 556303231Sdim Expansion.Function.Filenames[Expansion.FileID]); 557321369Sdim std::vector<CountedRegion> Regions; 558303231Sdim for (const auto &CR : Expansion.Function.CountedRegions) 559303231Sdim if (CR.FileID == Expansion.FileID) { 560303231Sdim Regions.push_back(CR); 561303231Sdim if (isExpansion(CR, Expansion.FileID)) 562303231Sdim ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function); 563303231Sdim } 564303231Sdim 565303231Sdim DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID 566303231Sdim << "\n"); 567303231Sdim ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions); 568303231Sdim 569303231Sdim return ExpansionCoverage; 570303231Sdim} 571303231Sdim 572321369Sdimstatic std::string getCoverageMapErrString(coveragemap_error Err) { 573303231Sdim switch (Err) { 574303231Sdim case coveragemap_error::success: 575303231Sdim return "Success"; 576303231Sdim case coveragemap_error::eof: 577303231Sdim return "End of File"; 578303231Sdim case coveragemap_error::no_data_found: 579303231Sdim return "No coverage data found"; 580303231Sdim case coveragemap_error::unsupported_version: 581303231Sdim return "Unsupported coverage format version"; 582303231Sdim case coveragemap_error::truncated: 583303231Sdim return "Truncated coverage data"; 584303231Sdim case coveragemap_error::malformed: 585303231Sdim return "Malformed coverage data"; 586303231Sdim } 587303231Sdim llvm_unreachable("A value of coveragemap_error has no message."); 588303231Sdim} 589303231Sdim 590321369Sdimnamespace { 591321369Sdim 592303231Sdim// FIXME: This class is only here to support the transition to llvm::Error. It 593303231Sdim// will be removed once this transition is complete. Clients should prefer to 594303231Sdim// deal with the Error value directly, rather than converting to error_code. 595303231Sdimclass CoverageMappingErrorCategoryType : public std::error_category { 596314564Sdim const char *name() const noexcept override { return "llvm.coveragemap"; } 597303231Sdim std::string message(int IE) const override { 598303231Sdim return getCoverageMapErrString(static_cast<coveragemap_error>(IE)); 599303231Sdim } 600303231Sdim}; 601321369Sdim 602303231Sdim} // end anonymous namespace 603303231Sdim 604303231Sdimstd::string CoverageMapError::message() const { 605303231Sdim return getCoverageMapErrString(Err); 606303231Sdim} 607303231Sdim 608303231Sdimstatic ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory; 609303231Sdim 610303231Sdimconst std::error_category &llvm::coverage::coveragemap_category() { 611303231Sdim return *ErrorCategory; 612303231Sdim} 613303231Sdim 614303231Sdimchar CoverageMapError::ID = 0; 615