CoverageMapping.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. //=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file contains support for clang's and llvm's instrumentation based
  11. // code coverage.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/ProfileData/CoverageMapping.h"
  15. #include "llvm/ADT/DenseMap.h"
  16. #include "llvm/ADT/Optional.h"
  17. #include "llvm/ADT/SmallBitVector.h"
  18. #include "llvm/ProfileData/CoverageMappingReader.h"
  19. #include "llvm/ProfileData/InstrProfReader.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/Support/Errc.h"
  22. #include "llvm/Support/ErrorHandling.h"
  23. #include "llvm/Support/ManagedStatic.h"
  24. #include "llvm/Support/Path.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. using namespace llvm;
  27. using namespace coverage;
  28. #define DEBUG_TYPE "coverage-mapping"
  29. Counter CounterExpressionBuilder::get(const CounterExpression &E) {
  30. auto It = ExpressionIndices.find(E);
  31. if (It != ExpressionIndices.end())
  32. return Counter::getExpression(It->second);
  33. unsigned I = Expressions.size();
  34. Expressions.push_back(E);
  35. ExpressionIndices[E] = I;
  36. return Counter::getExpression(I);
  37. }
  38. void CounterExpressionBuilder::extractTerms(
  39. Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) {
  40. switch (C.getKind()) {
  41. case Counter::Zero:
  42. break;
  43. case Counter::CounterValueReference:
  44. Terms.push_back(std::make_pair(C.getCounterID(), Sign));
  45. break;
  46. case Counter::Expression:
  47. const auto &E = Expressions[C.getExpressionID()];
  48. extractTerms(E.LHS, Sign, Terms);
  49. extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign,
  50. Terms);
  51. break;
  52. }
  53. }
  54. Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
  55. // Gather constant terms.
  56. llvm::SmallVector<std::pair<unsigned, int>, 32> Terms;
  57. extractTerms(ExpressionTree, +1, Terms);
  58. // If there are no terms, this is just a zero. The algorithm below assumes at
  59. // least one term.
  60. if (Terms.size() == 0)
  61. return Counter::getZero();
  62. // Group the terms by counter ID.
  63. std::sort(Terms.begin(), Terms.end(),
  64. [](const std::pair<unsigned, int> &LHS,
  65. const std::pair<unsigned, int> &RHS) {
  66. return LHS.first < RHS.first;
  67. });
  68. // Combine terms by counter ID to eliminate counters that sum to zero.
  69. auto Prev = Terms.begin();
  70. for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
  71. if (I->first == Prev->first) {
  72. Prev->second += I->second;
  73. continue;
  74. }
  75. ++Prev;
  76. *Prev = *I;
  77. }
  78. Terms.erase(++Prev, Terms.end());
  79. Counter C;
  80. // Create additions. We do this before subtractions to avoid constructs like
  81. // ((0 - X) + Y), as opposed to (Y - X).
  82. for (auto Term : Terms) {
  83. if (Term.second <= 0)
  84. continue;
  85. for (int I = 0; I < Term.second; ++I)
  86. if (C.isZero())
  87. C = Counter::getCounter(Term.first);
  88. else
  89. C = get(CounterExpression(CounterExpression::Add, C,
  90. Counter::getCounter(Term.first)));
  91. }
  92. // Create subtractions.
  93. for (auto Term : Terms) {
  94. if (Term.second >= 0)
  95. continue;
  96. for (int I = 0; I < -Term.second; ++I)
  97. C = get(CounterExpression(CounterExpression::Subtract, C,
  98. Counter::getCounter(Term.first)));
  99. }
  100. return C;
  101. }
  102. Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
  103. return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
  104. }
  105. Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
  106. return simplify(
  107. get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
  108. }
  109. void CounterMappingContext::dump(const Counter &C,
  110. llvm::raw_ostream &OS) const {
  111. switch (C.getKind()) {
  112. case Counter::Zero:
  113. OS << '0';
  114. return;
  115. case Counter::CounterValueReference:
  116. OS << '#' << C.getCounterID();
  117. break;
  118. case Counter::Expression: {
  119. if (C.getExpressionID() >= Expressions.size())
  120. return;
  121. const auto &E = Expressions[C.getExpressionID()];
  122. OS << '(';
  123. dump(E.LHS, OS);
  124. OS << (E.Kind == CounterExpression::Subtract ? " - " : " + ");
  125. dump(E.RHS, OS);
  126. OS << ')';
  127. break;
  128. }
  129. }
  130. if (CounterValues.empty())
  131. return;
  132. ErrorOr<int64_t> Value = evaluate(C);
  133. if (!Value)
  134. return;
  135. OS << '[' << *Value << ']';
  136. }
  137. ErrorOr<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
  138. switch (C.getKind()) {
  139. case Counter::Zero:
  140. return 0;
  141. case Counter::CounterValueReference:
  142. if (C.getCounterID() >= CounterValues.size())
  143. return make_error_code(errc::argument_out_of_domain);
  144. return CounterValues[C.getCounterID()];
  145. case Counter::Expression: {
  146. if (C.getExpressionID() >= Expressions.size())
  147. return make_error_code(errc::argument_out_of_domain);
  148. const auto &E = Expressions[C.getExpressionID()];
  149. ErrorOr<int64_t> LHS = evaluate(E.LHS);
  150. if (!LHS)
  151. return LHS;
  152. ErrorOr<int64_t> RHS = evaluate(E.RHS);
  153. if (!RHS)
  154. return RHS;
  155. return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS;
  156. }
  157. }
  158. llvm_unreachable("Unhandled CounterKind");
  159. }
  160. void FunctionRecordIterator::skipOtherFiles() {
  161. while (Current != Records.end() && !Filename.empty() &&
  162. Filename != Current->Filenames[0])
  163. ++Current;
  164. if (Current == Records.end())
  165. *this = FunctionRecordIterator();
  166. }
  167. ErrorOr<std::unique_ptr<CoverageMapping>>
  168. CoverageMapping::load(CoverageMappingReader &CoverageReader,
  169. IndexedInstrProfReader &ProfileReader) {
  170. auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
  171. std::vector<uint64_t> Counts;
  172. for (const auto &Record : CoverageReader) {
  173. CounterMappingContext Ctx(Record.Expressions);
  174. Counts.clear();
  175. if (std::error_code EC = ProfileReader.getFunctionCounts(
  176. Record.FunctionName, Record.FunctionHash, Counts)) {
  177. if (EC == instrprof_error::hash_mismatch) {
  178. Coverage->MismatchedFunctionCount++;
  179. continue;
  180. } else if (EC != instrprof_error::unknown_function)
  181. return EC;
  182. Counts.assign(Record.MappingRegions.size(), 0);
  183. }
  184. Ctx.setCounts(Counts);
  185. assert(!Record.MappingRegions.empty() && "Function has no regions");
  186. StringRef OrigFuncName = Record.FunctionName;
  187. if (!Record.Filenames.empty())
  188. OrigFuncName =
  189. getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
  190. FunctionRecord Function(OrigFuncName, Record.Filenames);
  191. for (const auto &Region : Record.MappingRegions) {
  192. ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
  193. if (!ExecutionCount)
  194. break;
  195. Function.pushRegion(Region, *ExecutionCount);
  196. }
  197. if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
  198. Coverage->MismatchedFunctionCount++;
  199. continue;
  200. }
  201. Coverage->Functions.push_back(std::move(Function));
  202. }
  203. return std::move(Coverage);
  204. }
  205. ErrorOr<std::unique_ptr<CoverageMapping>>
  206. CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
  207. StringRef Arch) {
  208. auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
  209. if (std::error_code EC = CounterMappingBuff.getError())
  210. return EC;
  211. auto CoverageReaderOrErr =
  212. BinaryCoverageReader::create(CounterMappingBuff.get(), Arch);
  213. if (std::error_code EC = CoverageReaderOrErr.getError())
  214. return EC;
  215. auto CoverageReader = std::move(CoverageReaderOrErr.get());
  216. auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
  217. if (auto EC = ProfileReaderOrErr.getError())
  218. return EC;
  219. auto ProfileReader = std::move(ProfileReaderOrErr.get());
  220. return load(*CoverageReader, *ProfileReader);
  221. }
  222. namespace {
  223. /// \brief Distributes functions into instantiation sets.
  224. ///
  225. /// An instantiation set is a collection of functions that have the same source
  226. /// code, ie, template functions specializations.
  227. class FunctionInstantiationSetCollector {
  228. typedef DenseMap<std::pair<unsigned, unsigned>,
  229. std::vector<const FunctionRecord *>> MapT;
  230. MapT InstantiatedFunctions;
  231. public:
  232. void insert(const FunctionRecord &Function, unsigned FileID) {
  233. auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
  234. while (I != E && I->FileID != FileID)
  235. ++I;
  236. assert(I != E && "function does not cover the given file");
  237. auto &Functions = InstantiatedFunctions[I->startLoc()];
  238. Functions.push_back(&Function);
  239. }
  240. MapT::iterator begin() { return InstantiatedFunctions.begin(); }
  241. MapT::iterator end() { return InstantiatedFunctions.end(); }
  242. };
  243. class SegmentBuilder {
  244. std::vector<CoverageSegment> Segments;
  245. SmallVector<const CountedRegion *, 8> ActiveRegions;
  246. /// Start a segment with no count specified.
  247. void startSegment(unsigned Line, unsigned Col) {
  248. DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
  249. Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
  250. }
  251. /// Start a segment with the given Region's count.
  252. void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
  253. const CountedRegion &Region) {
  254. if (Segments.empty())
  255. Segments.emplace_back(Line, Col, IsRegionEntry);
  256. CoverageSegment S = Segments.back();
  257. // Avoid creating empty regions.
  258. if (S.Line != Line || S.Col != Col) {
  259. Segments.emplace_back(Line, Col, IsRegionEntry);
  260. S = Segments.back();
  261. }
  262. DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
  263. // Set this region's count.
  264. if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) {
  265. DEBUG(dbgs() << " with count " << Region.ExecutionCount);
  266. Segments.back().setCount(Region.ExecutionCount);
  267. }
  268. DEBUG(dbgs() << "\n");
  269. }
  270. /// Start a segment for the given region.
  271. void startSegment(const CountedRegion &Region) {
  272. startSegment(Region.LineStart, Region.ColumnStart, true, Region);
  273. }
  274. /// Pop the top region off of the active stack, starting a new segment with
  275. /// the containing Region's count.
  276. void popRegion() {
  277. const CountedRegion *Active = ActiveRegions.back();
  278. unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
  279. ActiveRegions.pop_back();
  280. if (ActiveRegions.empty())
  281. startSegment(Line, Col);
  282. else
  283. startSegment(Line, Col, false, *ActiveRegions.back());
  284. }
  285. public:
  286. /// Build a list of CoverageSegments from a sorted list of Regions.
  287. std::vector<CoverageSegment> buildSegments(ArrayRef<CountedRegion> Regions) {
  288. const CountedRegion *PrevRegion = nullptr;
  289. for (const auto &Region : Regions) {
  290. // Pop any regions that end before this one starts.
  291. while (!ActiveRegions.empty() &&
  292. ActiveRegions.back()->endLoc() <= Region.startLoc())
  293. popRegion();
  294. if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() &&
  295. PrevRegion->endLoc() == Region.endLoc()) {
  296. if (Region.Kind == coverage::CounterMappingRegion::CodeRegion)
  297. Segments.back().addCount(Region.ExecutionCount);
  298. } else {
  299. // Add this region to the stack.
  300. ActiveRegions.push_back(&Region);
  301. startSegment(Region);
  302. }
  303. PrevRegion = &Region;
  304. }
  305. // Pop any regions that are left in the stack.
  306. while (!ActiveRegions.empty())
  307. popRegion();
  308. return Segments;
  309. }
  310. };
  311. }
  312. std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
  313. std::vector<StringRef> Filenames;
  314. for (const auto &Function : getCoveredFunctions())
  315. Filenames.insert(Filenames.end(), Function.Filenames.begin(),
  316. Function.Filenames.end());
  317. std::sort(Filenames.begin(), Filenames.end());
  318. auto Last = std::unique(Filenames.begin(), Filenames.end());
  319. Filenames.erase(Last, Filenames.end());
  320. return Filenames;
  321. }
  322. static SmallBitVector gatherFileIDs(StringRef SourceFile,
  323. const FunctionRecord &Function) {
  324. SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
  325. for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
  326. if (SourceFile == Function.Filenames[I])
  327. FilenameEquivalence[I] = true;
  328. return FilenameEquivalence;
  329. }
  330. static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
  331. const FunctionRecord &Function) {
  332. SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
  333. SmallBitVector FilenameEquivalence = gatherFileIDs(SourceFile, Function);
  334. for (const auto &CR : Function.CountedRegions)
  335. if (CR.Kind == CounterMappingRegion::ExpansionRegion &&
  336. FilenameEquivalence[CR.FileID])
  337. IsNotExpandedFile[CR.ExpandedFileID] = false;
  338. IsNotExpandedFile &= FilenameEquivalence;
  339. int I = IsNotExpandedFile.find_first();
  340. if (I == -1)
  341. return None;
  342. return I;
  343. }
  344. static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
  345. SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
  346. for (const auto &CR : Function.CountedRegions)
  347. if (CR.Kind == CounterMappingRegion::ExpansionRegion)
  348. IsNotExpandedFile[CR.ExpandedFileID] = false;
  349. int I = IsNotExpandedFile.find_first();
  350. if (I == -1)
  351. return None;
  352. return I;
  353. }
  354. /// Sort a nested sequence of regions from a single file.
  355. template <class It> static void sortNestedRegions(It First, It Last) {
  356. std::sort(First, Last,
  357. [](const CountedRegion &LHS, const CountedRegion &RHS) {
  358. if (LHS.startLoc() == RHS.startLoc())
  359. // When LHS completely contains RHS, we sort LHS first.
  360. return RHS.endLoc() < LHS.endLoc();
  361. return LHS.startLoc() < RHS.startLoc();
  362. });
  363. }
  364. static bool isExpansion(const CountedRegion &R, unsigned FileID) {
  365. return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
  366. }
  367. CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) {
  368. CoverageData FileCoverage(Filename);
  369. std::vector<coverage::CountedRegion> Regions;
  370. for (const auto &Function : Functions) {
  371. auto MainFileID = findMainViewFileID(Filename, Function);
  372. if (!MainFileID)
  373. continue;
  374. auto FileIDs = gatherFileIDs(Filename, Function);
  375. for (const auto &CR : Function.CountedRegions)
  376. if (FileIDs.test(CR.FileID)) {
  377. Regions.push_back(CR);
  378. if (isExpansion(CR, *MainFileID))
  379. FileCoverage.Expansions.emplace_back(CR, Function);
  380. }
  381. }
  382. sortNestedRegions(Regions.begin(), Regions.end());
  383. DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
  384. FileCoverage.Segments = SegmentBuilder().buildSegments(Regions);
  385. return FileCoverage;
  386. }
  387. std::vector<const FunctionRecord *>
  388. CoverageMapping::getInstantiations(StringRef Filename) {
  389. FunctionInstantiationSetCollector InstantiationSetCollector;
  390. for (const auto &Function : Functions) {
  391. auto MainFileID = findMainViewFileID(Filename, Function);
  392. if (!MainFileID)
  393. continue;
  394. InstantiationSetCollector.insert(Function, *MainFileID);
  395. }
  396. std::vector<const FunctionRecord *> Result;
  397. for (const auto &InstantiationSet : InstantiationSetCollector) {
  398. if (InstantiationSet.second.size() < 2)
  399. continue;
  400. Result.insert(Result.end(), InstantiationSet.second.begin(),
  401. InstantiationSet.second.end());
  402. }
  403. return Result;
  404. }
  405. CoverageData
  406. CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) {
  407. auto MainFileID = findMainViewFileID(Function);
  408. if (!MainFileID)
  409. return CoverageData();
  410. CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
  411. std::vector<coverage::CountedRegion> Regions;
  412. for (const auto &CR : Function.CountedRegions)
  413. if (CR.FileID == *MainFileID) {
  414. Regions.push_back(CR);
  415. if (isExpansion(CR, *MainFileID))
  416. FunctionCoverage.Expansions.emplace_back(CR, Function);
  417. }
  418. sortNestedRegions(Regions.begin(), Regions.end());
  419. DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
  420. FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
  421. return FunctionCoverage;
  422. }
  423. CoverageData
  424. CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) {
  425. CoverageData ExpansionCoverage(
  426. Expansion.Function.Filenames[Expansion.FileID]);
  427. std::vector<coverage::CountedRegion> Regions;
  428. for (const auto &CR : Expansion.Function.CountedRegions)
  429. if (CR.FileID == Expansion.FileID) {
  430. Regions.push_back(CR);
  431. if (isExpansion(CR, Expansion.FileID))
  432. ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
  433. }
  434. sortNestedRegions(Regions.begin(), Regions.end());
  435. DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
  436. << "\n");
  437. ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
  438. return ExpansionCoverage;
  439. }
  440. namespace {
  441. class CoverageMappingErrorCategoryType : public std::error_category {
  442. const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; }
  443. std::string message(int IE) const override {
  444. auto E = static_cast<coveragemap_error>(IE);
  445. switch (E) {
  446. case coveragemap_error::success:
  447. return "Success";
  448. case coveragemap_error::eof:
  449. return "End of File";
  450. case coveragemap_error::no_data_found:
  451. return "No coverage data found";
  452. case coveragemap_error::unsupported_version:
  453. return "Unsupported coverage format version";
  454. case coveragemap_error::truncated:
  455. return "Truncated coverage data";
  456. case coveragemap_error::malformed:
  457. return "Malformed coverage data";
  458. }
  459. llvm_unreachable("A value of coveragemap_error has no message.");
  460. }
  461. };
  462. }
  463. static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
  464. const std::error_category &llvm::coveragemap_category() {
  465. return *ErrorCategory;
  466. }