CoverageMapping.cpp revision 303231
12061Sjkh//=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=// 226510Sjfieber// 32061Sjkh// The LLVM Compiler Infrastructure 42061Sjkh// 515603Smarkm// This file is distributed under the University of Illinois Open Source 63197Scsgr// License. See LICENSE.TXT for details. 720710Sasami// 820710Sasami//===----------------------------------------------------------------------===// 93197Scsgr// 102061Sjkh// This file contains support for clang's and llvm's instrumentation based 1112483Speter// code coverage. 122160Scsgr// 132834Swollman//===----------------------------------------------------------------------===// 142061Sjkh 152061Sjkh#include "llvm/ProfileData/Coverage/CoverageMapping.h" 162160Scsgr#include "llvm/ADT/DenseMap.h" 1717308Speter#include "llvm/ADT/Optional.h" 1819320Sadam#include "llvm/ADT/SmallBitVector.h" 1921536Sjmacd#include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 2025399Sjb#include "llvm/ProfileData/InstrProfReader.h" 2125980Sasami#include "llvm/Support/Debug.h" 221594Srgrimes#include "llvm/Support/Errc.h" 2317308Speter#include "llvm/Support/ErrorHandling.h" 2417308Speter#include "llvm/Support/ManagedStatic.h" 2517308Speter#include "llvm/Support/Path.h" 2617308Speter#include "llvm/Support/raw_ostream.h" 2717308Speter 2817308Speterusing namespace llvm; 2917308Speterusing namespace coverage; 3019175Sbde 3119175Sbde#define DEBUG_TYPE "coverage-mapping" 3219175Sbde 3319175SbdeCounter CounterExpressionBuilder::get(const CounterExpression &E) { 3417308Speter auto It = ExpressionIndices.find(E); 3525647Sbde if (It != ExpressionIndices.end()) 3617308Speter return Counter::getExpression(It->second); 372061Sjkh unsigned I = Expressions.size(); 382061Sjkh Expressions.push_back(E); 391594Srgrimes ExpressionIndices[E] = I; 4025313Sbde return Counter::getExpression(I); 4125313Sbde} 4225313Sbde 4325313Sbdevoid CounterExpressionBuilder::extractTerms( 4425313Sbde Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) { 4525313Sbde switch (C.getKind()) { 4625313Sbde case Counter::Zero: 4725313Sbde break; 487407Srgrimes case Counter::CounterValueReference: 497108Sphk Terms.push_back(std::make_pair(C.getCounterID(), Sign)); 507108Sphk break; 517108Sphk case Counter::Expression: 527407Srgrimes const auto &E = Expressions[C.getExpressionID()]; 537407Srgrimes extractTerms(E.LHS, Sign, Terms); 547407Srgrimes extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign, 557108Sphk Terms); 562061Sjkh break; 572061Sjkh } 582061Sjkh} 5917308Speter 602061SjkhCounter CounterExpressionBuilder::simplify(Counter ExpressionTree) { 612061Sjkh // Gather constant terms. 622061Sjkh llvm::SmallVector<std::pair<unsigned, int>, 32> Terms; 632061Sjkh extractTerms(ExpressionTree, +1, Terms); 642061Sjkh 653197Scsgr // If there are no terms, this is just a zero. The algorithm below assumes at 662626Scsgr // least one term. 672626Scsgr if (Terms.size() == 0) 682061Sjkh return Counter::getZero(); 692061Sjkh 702061Sjkh // Group the terms by counter ID. 712061Sjkh std::sort(Terms.begin(), Terms.end(), 722061Sjkh [](const std::pair<unsigned, int> &LHS, 732061Sjkh const std::pair<unsigned, int> &RHS) { 7419320Sadam return LHS.first < RHS.first; 752061Sjkh }); 762061Sjkh 772061Sjkh // Combine terms by counter ID to eliminate counters that sum to zero. 782061Sjkh auto Prev = Terms.begin(); 792061Sjkh for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) { 802061Sjkh if (I->first == Prev->first) { 812061Sjkh Prev->second += I->second; 822061Sjkh continue; 832061Sjkh } 842061Sjkh ++Prev; 852061Sjkh *Prev = *I; 862834Swollman } 872834Swollman Terms.erase(++Prev, Terms.end()); 882834Swollman 892834Swollman Counter C; 902834Swollman // Create additions. We do this before subtractions to avoid constructs like 912834Swollman // ((0 - X) + Y), as opposed to (Y - X). 921594Srgrimes for (auto Term : Terms) { 934486Sphk if (Term.second <= 0) 944486Sphk continue; 954486Sphk for (int I = 0; I < Term.second; ++I) 964486Sphk if (C.isZero()) 974486Sphk C = Counter::getCounter(Term.first); 982061Sjkh else 992061Sjkh C = get(CounterExpression(CounterExpression::Add, C, 10025979Sjkh Counter::getCounter(Term.first))); 10125979Sjkh } 10225979Sjkh 10325979Sjkh // Create subtractions. 1042061Sjkh for (auto Term : Terms) { 10525979Sjkh if (Term.second >= 0) 1062061Sjkh continue; 1072061Sjkh for (int I = 0; I < -Term.second; ++I) 10817308Speter C = get(CounterExpression(CounterExpression::Subtract, C, 1092061Sjkh Counter::getCounter(Term.first))); 1102061Sjkh } 1112061Sjkh return C; 1122061Sjkh} 1132061Sjkh 11412483SpeterCounter CounterExpressionBuilder::add(Counter LHS, Counter RHS) { 11512483Speter return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS))); 11612483Speter} 11712483Speter 1182061SjkhCounter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) { 1192061Sjkh return simplify( 1208854Srgrimes get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); 1212061Sjkh} 1222061Sjkh 12312483Spetervoid CounterMappingContext::dump(const Counter &C, 1242061Sjkh llvm::raw_ostream &OS) const { 12518714Sache switch (C.getKind()) { 12618714Sache case Counter::Zero: 12718714Sache OS << '0'; 12817308Speter return; 12917308Speter case Counter::CounterValueReference: 13017308Speter OS << '#' << C.getCounterID(); 13117308Speter break; 13221536Sjmacd case Counter::Expression: { 13315603Smarkm if (C.getExpressionID() >= Expressions.size()) 13417308Speter return; 13517308Speter const auto &E = Expressions[C.getExpressionID()]; 13617308Speter OS << '('; 13717308Speter dump(E.LHS, OS); 13817308Speter OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); 13917308Speter dump(E.RHS, OS); 14017308Speter OS << ')'; 14117308Speter break; 14217308Speter } 14318362Sjkh } 14419966Sache if (CounterValues.empty()) 14518362Sjkh return; 14617308Speter Expected<int64_t> Value = evaluate(C); 14717308Speter if (auto E = Value.takeError()) { 14817308Speter llvm::consumeError(std::move(E)); 14917308Speter return; 15017308Speter } 15117308Speter OS << '[' << *Value << ']'; 15216550Sjkh} 1532061Sjkh 15417308SpeterExpected<int64_t> CounterMappingContext::evaluate(const Counter &C) const { 1552061Sjkh switch (C.getKind()) { 15617308Speter case Counter::Zero: 1572061Sjkh return 0; 15817308Speter case Counter::CounterValueReference: 15917308Speter if (C.getCounterID() >= CounterValues.size()) 16017308Speter return errorCodeToError(errc::argument_out_of_domain); 16117308Speter return CounterValues[C.getCounterID()]; 16217308Speter case Counter::Expression: { 16317308Speter if (C.getExpressionID() >= Expressions.size()) 16417466Speter return errorCodeToError(errc::argument_out_of_domain); 16517308Speter const auto &E = Expressions[C.getExpressionID()]; 16617308Speter Expected<int64_t> LHS = evaluate(E.LHS); 16717466Speter if (!LHS) 16817308Speter return LHS; 16917308Speter Expected<int64_t> RHS = evaluate(E.RHS); 17017308Speter if (!RHS) 17117308Speter return RHS; 17217466Speter return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS; 17317308Speter } 17417308Speter } 17517308Speter llvm_unreachable("Unhandled CounterKind"); 17617308Speter} 17717308Speter 17817308Spetervoid FunctionRecordIterator::skipOtherFiles() { 17917308Speter while (Current != Records.end() && !Filename.empty() && 18017308Speter Filename != Current->Filenames[0]) 18117308Speter ++Current; 18217308Speter if (Current == Records.end()) 18317308Speter *this = FunctionRecordIterator(); 18417308Speter} 18517308Speter 18617308SpeterExpected<std::unique_ptr<CoverageMapping>> 18717308SpeterCoverageMapping::load(CoverageMappingReader &CoverageReader, 18817308Speter IndexedInstrProfReader &ProfileReader) { 18917308Speter auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); 19017308Speter 19117308Speter std::vector<uint64_t> Counts; 19217308Speter for (const auto &Record : CoverageReader) { 19317308Speter CounterMappingContext Ctx(Record.Expressions); 19417308Speter 19517308Speter Counts.clear(); 19617308Speter if (Error E = ProfileReader.getFunctionCounts( 19717308Speter Record.FunctionName, Record.FunctionHash, Counts)) { 19817308Speter instrprof_error IPE = InstrProfError::take(std::move(E)); 19917308Speter if (IPE == instrprof_error::hash_mismatch) { 20026510Sjfieber Coverage->MismatchedFunctionCount++; 20117308Speter continue; 20217308Speter } else if (IPE != instrprof_error::unknown_function) 20317308Speter return make_error<InstrProfError>(IPE); 20417308Speter Counts.assign(Record.MappingRegions.size(), 0); 20517962Speter } 20617308Speter Ctx.setCounts(Counts); 20717962Speter 20817962Speter assert(!Record.MappingRegions.empty() && "Function has no regions"); 20917962Speter 21017962Speter StringRef OrigFuncName = Record.FunctionName; 21117962Speter if (Record.Filenames.empty()) 21217962Speter OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName); 21317962Speter else 21417962Speter OrigFuncName = 21517962Speter getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]); 21617962Speter FunctionRecord Function(OrigFuncName, Record.Filenames); 21717962Speter for (const auto &Region : Record.MappingRegions) { 21817962Speter Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); 21917962Speter if (auto E = ExecutionCount.takeError()) { 22017962Speter llvm::consumeError(std::move(E)); 22117962Speter break; 22217308Speter } 22316550Sjkh Function.pushRegion(Region, *ExecutionCount); 22417308Speter } 22517308Speter if (Function.CountedRegions.size() != Record.MappingRegions.size()) { 22617308Speter Coverage->MismatchedFunctionCount++; 22717308Speter continue; 22816550Sjkh } 22916550Sjkh 23017308Speter Coverage->Functions.push_back(std::move(Function)); 23117308Speter } 23219966Sache 23317962Speter return std::move(Coverage); 2342061Sjkh} 23517308Speter 23617308SpeterExpected<std::unique_ptr<CoverageMapping>> 23717308SpeterCoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename, 23817308Speter StringRef Arch) { 23917308Speter auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename); 24017308Speter if (std::error_code EC = CounterMappingBuff.getError()) 24117308Speter return errorCodeToError(EC); 24217308Speter auto CoverageReaderOrErr = 24312483Speter BinaryCoverageReader::create(CounterMappingBuff.get(), Arch); 24417308Speter if (Error E = CoverageReaderOrErr.takeError()) 24512483Speter return std::move(E); 24617308Speter auto CoverageReader = std::move(CoverageReaderOrErr.get()); 24712483Speter auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename); 2482061Sjkh if (Error E = ProfileReaderOrErr.takeError()) 24917962Speter return std::move(E); 25017962Speter auto ProfileReader = std::move(ProfileReaderOrErr.get()); 25117308Speter return load(*CoverageReader, *ProfileReader); 25217962Speter} 25317962Speter 25417962Speternamespace { 25517962Speter/// \brief Distributes functions into instantiation sets. 25617308Speter/// 2572061Sjkh/// An instantiation set is a collection of functions that have the same source 25817308Speter/// code, ie, template functions specializations. 25917308Speterclass FunctionInstantiationSetCollector { 26017308Speter typedef DenseMap<std::pair<unsigned, unsigned>, 26117308Speter std::vector<const FunctionRecord *>> MapT; 26217308Speter MapT InstantiatedFunctions; 26317308Speter 26417308Speterpublic: 2652302Spaul void insert(const FunctionRecord &Function, unsigned FileID) { 2662302Spaul auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end(); 2672302Spaul while (I != E && I->FileID != FileID) 2682302Spaul ++I; 2692302Spaul assert(I != E && "function does not cover the given file"); 27018714Sache auto &Functions = InstantiatedFunctions[I->startLoc()]; 27110760Sache Functions.push_back(&Function); 27218714Sache } 2732302Spaul 27410760Sache MapT::iterator begin() { return InstantiatedFunctions.begin(); } 27518714Sache 27610760Sache MapT::iterator end() { return InstantiatedFunctions.end(); } 27710760Sache}; 2782302Spaul 2792302Spaulclass SegmentBuilder { 2802302Spaul std::vector<CoverageSegment> &Segments; 2812302Spaul SmallVector<const CountedRegion *, 8> ActiveRegions; 28216591Spst 2832302Spaul SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {} 2842302Spaul 28517308Speter /// Start a segment with no count specified. 28617308Speter void startSegment(unsigned Line, unsigned Col) { 28717308Speter DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n"); 28817308Speter Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false); 28917308Speter } 29017308Speter 29117308Speter /// Start a segment with the given Region's count. 2922061Sjkh void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry, 29317308Speter const CountedRegion &Region) { 2942061Sjkh // Avoid creating empty regions. 29517308Speter if (!Segments.empty() && Segments.back().Line == Line && 29617308Speter Segments.back().Col == Col) 29717308Speter Segments.pop_back(); 29817308Speter DEBUG(dbgs() << "Segment at " << Line << ":" << Col); 29917308Speter // Set this region's count. 30017308Speter if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) { 30117308Speter DEBUG(dbgs() << " with count " << Region.ExecutionCount); 30217308Speter Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry); 30317308Speter } else 30417308Speter Segments.emplace_back(Line, Col, IsRegionEntry); 30517308Speter DEBUG(dbgs() << "\n"); 30617308Speter } 30717308Speter 30817308Speter /// Start a segment for the given region. 3092061Sjkh void startSegment(const CountedRegion &Region) { 31017308Speter startSegment(Region.LineStart, Region.ColumnStart, true, Region); 31117308Speter } 31217308Speter 31317308Speter /// Pop the top region off of the active stack, starting a new segment with 31417308Speter /// the containing Region's count. 31517308Speter void popRegion() { 3163626Swollman const CountedRegion *Active = ActiveRegions.back(); 3173626Swollman unsigned Line = Active->LineEnd, Col = Active->ColumnEnd; 3183626Swollman ActiveRegions.pop_back(); 3193626Swollman if (ActiveRegions.empty()) 3203626Swollman startSegment(Line, Col); 3213626Swollman else 3223626Swollman startSegment(Line, Col, false, *ActiveRegions.back()); 3233626Swollman } 3243626Swollman 3253626Swollman void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) { 3263626Swollman for (const auto &Region : Regions) { 3277059Sroberto // Pop any regions that end before this one starts. 3283626Swollman while (!ActiveRegions.empty() && 3293626Swollman ActiveRegions.back()->endLoc() <= Region.startLoc()) 3303626Swollman popRegion(); 3313626Swollman // Add this region to the stack. 3323626Swollman ActiveRegions.push_back(&Region); 3333626Swollman startSegment(Region); 3343626Swollman } 33517308Speter // Pop any regions that are left in the stack. 33617308Speter while (!ActiveRegions.empty()) 33717308Speter popRegion(); 33817308Speter } 33917308Speter 34017308Speter /// Sort a nested sequence of regions from a single file. 34117308Speter static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) { 34217308Speter std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS, 34317308Speter const CountedRegion &RHS) { 34417308Speter if (LHS.startLoc() != RHS.startLoc()) 3453626Swollman return LHS.startLoc() < RHS.startLoc(); 34617308Speter if (LHS.endLoc() != RHS.endLoc()) 34717308Speter // When LHS completely contains RHS, we sort LHS first. 34817308Speter return RHS.endLoc() < LHS.endLoc(); 34917308Speter // If LHS and RHS cover the same area, we need to sort them according 35017308Speter // to their kinds so that the most suitable region will become "active" 35117308Speter // in combineRegions(). Because we accumulate counter values only from 35217308Speter // regions of the same kind as the first region of the area, prefer 35317308Speter // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion. 35417308Speter static_assert(coverage::CounterMappingRegion::CodeRegion < 35517308Speter coverage::CounterMappingRegion::ExpansionRegion && 35617308Speter coverage::CounterMappingRegion::ExpansionRegion < 35717308Speter coverage::CounterMappingRegion::SkippedRegion, 35817820Sjkh "Unexpected order of region kind values"); 35917308Speter return LHS.Kind < RHS.Kind; 36017820Sjkh }); 36117308Speter } 36217820Sjkh 36317467Speter /// Combine counts of regions which cover the same area. 36417308Speter static ArrayRef<CountedRegion> 36517308Speter combineRegions(MutableArrayRef<CountedRegion> Regions) { 36617308Speter if (Regions.empty()) 36717308Speter return Regions; 36817308Speter auto Active = Regions.begin(); 36917308Speter auto End = Regions.end(); 37017308Speter for (auto I = Regions.begin() + 1; I != End; ++I) { 37117308Speter if (Active->startLoc() != I->startLoc() || 37217820Sjkh Active->endLoc() != I->endLoc()) { 37317820Sjkh // Shift to the next region. 37417308Speter ++Active; 37517308Speter if (Active != I) 37617308Speter *Active = *I; 37717308Speter continue; 37814119Speter } 3792061Sjkh // Merge duplicate region. 3807130Srgrimes // If CodeRegions and ExpansionRegions cover the same area, it's probably 3817130Srgrimes // a macro which is fully expanded to another macro. In that case, we need 3827130Srgrimes // to accumulate counts only from CodeRegions, or else the area will be 3832061Sjkh // counted twice. 38425783Speter // On the other hand, a macro may have a nested macro in its body. If the 38517308Speter // outer macro is used several times, the ExpansionRegion for the nested 3862685Srgrimes // macro will also be added several times. These ExpansionRegions cover 3876927Snate // the same source locations and have to be combined to reach the correct 38818674Speter // value for that area. 3892685Srgrimes // We add counts of the regions of the same kind as the active region 3903518Sache // to handle the both situations. 39126504Sjhay if (I->Kind == Active->Kind) 3923197Scsgr Active->ExecutionCount += I->ExecutionCount; 3933197Scsgr } 39412166Sjkh return Regions.drop_back(std::distance(++Active, End)); 39512485Sjkh } 3963197Scsgr 39725313Sbdepublic: 39826152Speter /// Build a list of CoverageSegments from a list of Regions. 3992061Sjkh static std::vector<CoverageSegment> 4002061Sjkh buildSegments(MutableArrayRef<CountedRegion> Regions) { 4012061Sjkh std::vector<CoverageSegment> Segments; 40216786Snate SegmentBuilder Builder(Segments); 4032883Sphk 40417308Speter sortNestedRegions(Regions); 40517308Speter ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions); 4067281Srgrimes 4073242Spaul Builder.buildSegmentsImpl(CombinedRegions); 4083242Spaul return Segments; 4097171Sats } 4102061Sjkh}; 4113213Spst} 41217308Speter 41317308Speterstd::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { 4145749Swollman std::vector<StringRef> Filenames; 4155772Swollman for (const auto &Function : getCoveredFunctions()) 41617308Speter Filenames.insert(Filenames.end(), Function.Filenames.begin(), 41717308Speter Function.Filenames.end()); 41826504Sjhay std::sort(Filenames.begin(), Filenames.end()); 4192061Sjkh auto Last = std::unique(Filenames.begin(), Filenames.end()); 42017308Speter Filenames.erase(Last, Filenames.end()); 42117308Speter return Filenames; 42217308Speter} 4235366Snate 42417820Sjkhstatic SmallBitVector gatherFileIDs(StringRef SourceFile, 42517467Speter const FunctionRecord &Function) { 42617820Sjkh SmallBitVector FilenameEquivalence(Function.Filenames.size(), false); 42717308Speter for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) 42818674Speter if (SourceFile == Function.Filenames[I]) 42918674Speter FilenameEquivalence[I] = true; 43017820Sjkh return FilenameEquivalence; 43117308Speter} 43217820Sjkh 43317308Speter/// Return the ID of the file where the definition of the function is located. 43417820Sjkhstatic Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) { 43517308Speter SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); 43617820Sjkh for (const auto &CR : Function.CountedRegions) 43717308Speter if (CR.Kind == CounterMappingRegion::ExpansionRegion) 43817820Sjkh IsNotExpandedFile[CR.ExpandedFileID] = false; 43917308Speter int I = IsNotExpandedFile.find_first(); 4405728Swollman if (I == -1) 44117820Sjkh return None; 44217308Speter return I; 44321922Sjkh} 44421922Sjkh 44518392Speter/// Check if SourceFile is the file that contains the definition of 44618392Speter/// the Function. Return the ID of the file in that case or None otherwise. 44718392Speterstatic Optional<unsigned> findMainViewFileID(StringRef SourceFile, 44818392Speter const FunctionRecord &Function) { 44918392Speter Optional<unsigned> I = findMainViewFileID(Function); 45018392Speter if (I && SourceFile == Function.Filenames[*I]) 4515366Snate return I; 45217308Speter return None; 45317308Speter} 45417308Speter 4552061Sjkhstatic bool isExpansion(const CountedRegion &R, unsigned FileID) { 45624754Sjdp return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; 45724754Sjdp} 45824754Sjdp 45924754SjdpCoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { 4608295Srgrimes CoverageData FileCoverage(Filename); 46117820Sjkh std::vector<coverage::CountedRegion> Regions; 46217308Speter 4638295Srgrimes for (const auto &Function : Functions) { 4648489Srgrimes auto MainFileID = findMainViewFileID(Filename, Function); 46517820Sjkh auto FileIDs = gatherFileIDs(Filename, Function); 46617308Speter for (const auto &CR : Function.CountedRegions) 4678489Srgrimes if (FileIDs.test(CR.FileID)) { 4688489Srgrimes Regions.push_back(CR); 46917820Sjkh if (MainFileID && isExpansion(CR, *MainFileID)) 47017308Speter FileCoverage.Expansions.emplace_back(CR, Function); 4718489Srgrimes } 4728295Srgrimes } 47317820Sjkh 47417308Speter DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n"); 4758295Srgrimes FileCoverage.Segments = SegmentBuilder::buildSegments(Regions); 4762160Scsgr 47717820Sjkh return FileCoverage; 47817308Speter} 4792160Scsgr 4802279Spaulstd::vector<const FunctionRecord *> 48117820SjkhCoverageMapping::getInstantiations(StringRef Filename) const { 48217308Speter FunctionInstantiationSetCollector InstantiationSetCollector; 4832279Spaul for (const auto &Function : Functions) { 48417234Sjraynard auto MainFileID = findMainViewFileID(Filename, Function); 48517820Sjkh if (!MainFileID) 48617308Speter continue; 48711772Snate InstantiationSetCollector.insert(Function, *MainFileID); 4883197Scsgr } 48917820Sjkh 49017308Speter std::vector<const FunctionRecord *> Result; 4912626Scsgr for (const auto &InstantiationSet : InstantiationSetCollector) { 4928304Srgrimes if (InstantiationSet.second.size() < 2) 49317820Sjkh continue; 49417308Speter Result.insert(Result.end(), InstantiationSet.second.begin(), 4958304Srgrimes InstantiationSet.second.end()); 4962061Sjkh } 49717308Speter return Result; 49817308Speter} 49917308Speter 50017308SpeterCoverageData 50111806SphkCoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const { 50219175Sbde auto MainFileID = findMainViewFileID(Function); 50321673Sjkh if (!MainFileID) 50421536Sjmacd return CoverageData(); 50519175Sbde 50619175Sbde CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); 50719175Sbde std::vector<coverage::CountedRegion> Regions; 50819175Sbde for (const auto &CR : Function.CountedRegions) 50919175Sbde if (CR.FileID == *MainFileID) { 51017308Speter Regions.push_back(CR); 51119175Sbde if (isExpansion(CR, *MainFileID)) 5122061Sjkh FunctionCoverage.Expansions.emplace_back(CR, Function); 5131594Srgrimes } 514 515 DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n"); 516 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions); 517 518 return FunctionCoverage; 519} 520 521CoverageData CoverageMapping::getCoverageForExpansion( 522 const ExpansionRecord &Expansion) const { 523 CoverageData ExpansionCoverage( 524 Expansion.Function.Filenames[Expansion.FileID]); 525 std::vector<coverage::CountedRegion> Regions; 526 for (const auto &CR : Expansion.Function.CountedRegions) 527 if (CR.FileID == Expansion.FileID) { 528 Regions.push_back(CR); 529 if (isExpansion(CR, Expansion.FileID)) 530 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function); 531 } 532 533 DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID 534 << "\n"); 535 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions); 536 537 return ExpansionCoverage; 538} 539 540namespace { 541std::string getCoverageMapErrString(coveragemap_error Err) { 542 switch (Err) { 543 case coveragemap_error::success: 544 return "Success"; 545 case coveragemap_error::eof: 546 return "End of File"; 547 case coveragemap_error::no_data_found: 548 return "No coverage data found"; 549 case coveragemap_error::unsupported_version: 550 return "Unsupported coverage format version"; 551 case coveragemap_error::truncated: 552 return "Truncated coverage data"; 553 case coveragemap_error::malformed: 554 return "Malformed coverage data"; 555 } 556 llvm_unreachable("A value of coveragemap_error has no message."); 557} 558 559// FIXME: This class is only here to support the transition to llvm::Error. It 560// will be removed once this transition is complete. Clients should prefer to 561// deal with the Error value directly, rather than converting to error_code. 562class CoverageMappingErrorCategoryType : public std::error_category { 563 const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; } 564 std::string message(int IE) const override { 565 return getCoverageMapErrString(static_cast<coveragemap_error>(IE)); 566 } 567}; 568} // end anonymous namespace 569 570std::string CoverageMapError::message() const { 571 return getCoverageMapErrString(Err); 572} 573 574static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory; 575 576const std::error_category &llvm::coverage::coveragemap_category() { 577 return *ErrorCategory; 578} 579 580char CoverageMapError::ID = 0; 581