2
0

CoverageMapping.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. /// Get the function name from the record, removing the filename prefix if
  168. /// necessary.
  169. static StringRef getFuncNameWithoutPrefix(const CoverageMappingRecord &Record) {
  170. StringRef FunctionName = Record.FunctionName;
  171. if (Record.Filenames.empty())
  172. return FunctionName;
  173. StringRef Filename = sys::path::filename(Record.Filenames[0]);
  174. if (FunctionName.startswith(Filename))
  175. FunctionName = FunctionName.drop_front(Filename.size() + 1);
  176. return FunctionName;
  177. }
  178. ErrorOr<std::unique_ptr<CoverageMapping>>
  179. CoverageMapping::load(CoverageMappingReader &CoverageReader,
  180. IndexedInstrProfReader &ProfileReader) {
  181. auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
  182. std::vector<uint64_t> Counts;
  183. for (const auto &Record : CoverageReader) {
  184. CounterMappingContext Ctx(Record.Expressions);
  185. Counts.clear();
  186. if (std::error_code EC = ProfileReader.getFunctionCounts(
  187. Record.FunctionName, Record.FunctionHash, Counts)) {
  188. if (EC == instrprof_error::hash_mismatch) {
  189. Coverage->MismatchedFunctionCount++;
  190. continue;
  191. } else if (EC != instrprof_error::unknown_function)
  192. return EC;
  193. Counts.assign(Record.MappingRegions.size(), 0);
  194. }
  195. Ctx.setCounts(Counts);
  196. assert(!Record.MappingRegions.empty() && "Function has no regions");
  197. FunctionRecord Function(getFuncNameWithoutPrefix(Record), Record.Filenames);
  198. for (const auto &Region : Record.MappingRegions) {
  199. ErrorOr<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
  200. if (!ExecutionCount)
  201. break;
  202. Function.pushRegion(Region, *ExecutionCount);
  203. }
  204. if (Function.CountedRegions.size() != Record.MappingRegions.size()) {
  205. Coverage->MismatchedFunctionCount++;
  206. continue;
  207. }
  208. Coverage->Functions.push_back(std::move(Function));
  209. }
  210. return std::move(Coverage);
  211. }
  212. ErrorOr<std::unique_ptr<CoverageMapping>>
  213. CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
  214. StringRef Arch) {
  215. auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
  216. if (std::error_code EC = CounterMappingBuff.getError())
  217. return EC;
  218. auto CoverageReaderOrErr =
  219. BinaryCoverageReader::create(CounterMappingBuff.get(), Arch);
  220. if (std::error_code EC = CoverageReaderOrErr.getError())
  221. return EC;
  222. auto CoverageReader = std::move(CoverageReaderOrErr.get());
  223. auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename);
  224. if (auto EC = ProfileReaderOrErr.getError())
  225. return EC;
  226. auto ProfileReader = std::move(ProfileReaderOrErr.get());
  227. return load(*CoverageReader, *ProfileReader);
  228. }
  229. namespace {
  230. /// \brief Distributes functions into instantiation sets.
  231. ///
  232. /// An instantiation set is a collection of functions that have the same source
  233. /// code, ie, template functions specializations.
  234. class FunctionInstantiationSetCollector {
  235. typedef DenseMap<std::pair<unsigned, unsigned>,
  236. std::vector<const FunctionRecord *>> MapT;
  237. MapT InstantiatedFunctions;
  238. public:
  239. void insert(const FunctionRecord &Function, unsigned FileID) {
  240. auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end();
  241. while (I != E && I->FileID != FileID)
  242. ++I;
  243. assert(I != E && "function does not cover the given file");
  244. auto &Functions = InstantiatedFunctions[I->startLoc()];
  245. Functions.push_back(&Function);
  246. }
  247. MapT::iterator begin() { return InstantiatedFunctions.begin(); }
  248. MapT::iterator end() { return InstantiatedFunctions.end(); }
  249. };
  250. class SegmentBuilder {
  251. std::vector<CoverageSegment> Segments;
  252. SmallVector<const CountedRegion *, 8> ActiveRegions;
  253. /// Start a segment with no count specified.
  254. void startSegment(unsigned Line, unsigned Col) {
  255. DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n");
  256. Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false);
  257. }
  258. /// Start a segment with the given Region's count.
  259. void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
  260. const CountedRegion &Region) {
  261. if (Segments.empty())
  262. Segments.emplace_back(Line, Col, IsRegionEntry);
  263. CoverageSegment S = Segments.back();
  264. // Avoid creating empty regions.
  265. if (S.Line != Line || S.Col != Col) {
  266. Segments.emplace_back(Line, Col, IsRegionEntry);
  267. S = Segments.back();
  268. }
  269. DEBUG(dbgs() << "Segment at " << Line << ":" << Col);
  270. // Set this region's count.
  271. if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) {
  272. DEBUG(dbgs() << " with count " << Region.ExecutionCount);
  273. Segments.back().setCount(Region.ExecutionCount);
  274. }
  275. DEBUG(dbgs() << "\n");
  276. }
  277. /// Start a segment for the given region.
  278. void startSegment(const CountedRegion &Region) {
  279. startSegment(Region.LineStart, Region.ColumnStart, true, Region);
  280. }
  281. /// Pop the top region off of the active stack, starting a new segment with
  282. /// the containing Region's count.
  283. void popRegion() {
  284. const CountedRegion *Active = ActiveRegions.back();
  285. unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
  286. ActiveRegions.pop_back();
  287. if (ActiveRegions.empty())
  288. startSegment(Line, Col);
  289. else
  290. startSegment(Line, Col, false, *ActiveRegions.back());
  291. }
  292. public:
  293. /// Build a list of CoverageSegments from a sorted list of Regions.
  294. std::vector<CoverageSegment> buildSegments(ArrayRef<CountedRegion> Regions) {
  295. const CountedRegion *PrevRegion = nullptr;
  296. for (const auto &Region : Regions) {
  297. // Pop any regions that end before this one starts.
  298. while (!ActiveRegions.empty() &&
  299. ActiveRegions.back()->endLoc() <= Region.startLoc())
  300. popRegion();
  301. if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() &&
  302. PrevRegion->endLoc() == Region.endLoc()) {
  303. if (Region.Kind == coverage::CounterMappingRegion::CodeRegion)
  304. Segments.back().addCount(Region.ExecutionCount);
  305. } else {
  306. // Add this region to the stack.
  307. ActiveRegions.push_back(&Region);
  308. startSegment(Region);
  309. }
  310. PrevRegion = &Region;
  311. }
  312. // Pop any regions that are left in the stack.
  313. while (!ActiveRegions.empty())
  314. popRegion();
  315. return Segments;
  316. }
  317. };
  318. }
  319. std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
  320. std::vector<StringRef> Filenames;
  321. for (const auto &Function : getCoveredFunctions())
  322. Filenames.insert(Filenames.end(), Function.Filenames.begin(),
  323. Function.Filenames.end());
  324. std::sort(Filenames.begin(), Filenames.end());
  325. auto Last = std::unique(Filenames.begin(), Filenames.end());
  326. Filenames.erase(Last, Filenames.end());
  327. return Filenames;
  328. }
  329. static SmallBitVector gatherFileIDs(StringRef SourceFile,
  330. const FunctionRecord &Function) {
  331. SmallBitVector FilenameEquivalence(Function.Filenames.size(), false);
  332. for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I)
  333. if (SourceFile == Function.Filenames[I])
  334. FilenameEquivalence[I] = true;
  335. return FilenameEquivalence;
  336. }
  337. static Optional<unsigned> findMainViewFileID(StringRef SourceFile,
  338. const FunctionRecord &Function) {
  339. SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
  340. SmallBitVector FilenameEquivalence = gatherFileIDs(SourceFile, Function);
  341. for (const auto &CR : Function.CountedRegions)
  342. if (CR.Kind == CounterMappingRegion::ExpansionRegion &&
  343. FilenameEquivalence[CR.FileID])
  344. IsNotExpandedFile[CR.ExpandedFileID] = false;
  345. IsNotExpandedFile &= FilenameEquivalence;
  346. int I = IsNotExpandedFile.find_first();
  347. if (I == -1)
  348. return None;
  349. return I;
  350. }
  351. static Optional<unsigned> findMainViewFileID(const FunctionRecord &Function) {
  352. SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
  353. for (const auto &CR : Function.CountedRegions)
  354. if (CR.Kind == CounterMappingRegion::ExpansionRegion)
  355. IsNotExpandedFile[CR.ExpandedFileID] = false;
  356. int I = IsNotExpandedFile.find_first();
  357. if (I == -1)
  358. return None;
  359. return I;
  360. }
  361. /// Sort a nested sequence of regions from a single file.
  362. template <class It> static void sortNestedRegions(It First, It Last) {
  363. std::sort(First, Last,
  364. [](const CountedRegion &LHS, const CountedRegion &RHS) {
  365. if (LHS.startLoc() == RHS.startLoc())
  366. // When LHS completely contains RHS, we sort LHS first.
  367. return RHS.endLoc() < LHS.endLoc();
  368. return LHS.startLoc() < RHS.startLoc();
  369. });
  370. }
  371. static bool isExpansion(const CountedRegion &R, unsigned FileID) {
  372. return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
  373. }
  374. CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) {
  375. CoverageData FileCoverage(Filename);
  376. std::vector<coverage::CountedRegion> Regions;
  377. for (const auto &Function : Functions) {
  378. auto MainFileID = findMainViewFileID(Filename, Function);
  379. if (!MainFileID)
  380. continue;
  381. auto FileIDs = gatherFileIDs(Filename, Function);
  382. for (const auto &CR : Function.CountedRegions)
  383. if (FileIDs.test(CR.FileID)) {
  384. Regions.push_back(CR);
  385. if (isExpansion(CR, *MainFileID))
  386. FileCoverage.Expansions.emplace_back(CR, Function);
  387. }
  388. }
  389. sortNestedRegions(Regions.begin(), Regions.end());
  390. DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
  391. FileCoverage.Segments = SegmentBuilder().buildSegments(Regions);
  392. return FileCoverage;
  393. }
  394. std::vector<const FunctionRecord *>
  395. CoverageMapping::getInstantiations(StringRef Filename) {
  396. FunctionInstantiationSetCollector InstantiationSetCollector;
  397. for (const auto &Function : Functions) {
  398. auto MainFileID = findMainViewFileID(Filename, Function);
  399. if (!MainFileID)
  400. continue;
  401. InstantiationSetCollector.insert(Function, *MainFileID);
  402. }
  403. std::vector<const FunctionRecord *> Result;
  404. for (const auto &InstantiationSet : InstantiationSetCollector) {
  405. if (InstantiationSet.second.size() < 2)
  406. continue;
  407. Result.insert(Result.end(), InstantiationSet.second.begin(),
  408. InstantiationSet.second.end());
  409. }
  410. return Result;
  411. }
  412. CoverageData
  413. CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) {
  414. auto MainFileID = findMainViewFileID(Function);
  415. if (!MainFileID)
  416. return CoverageData();
  417. CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
  418. std::vector<coverage::CountedRegion> Regions;
  419. for (const auto &CR : Function.CountedRegions)
  420. if (CR.FileID == *MainFileID) {
  421. Regions.push_back(CR);
  422. if (isExpansion(CR, *MainFileID))
  423. FunctionCoverage.Expansions.emplace_back(CR, Function);
  424. }
  425. sortNestedRegions(Regions.begin(), Regions.end());
  426. DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n");
  427. FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
  428. return FunctionCoverage;
  429. }
  430. CoverageData
  431. CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) {
  432. CoverageData ExpansionCoverage(
  433. Expansion.Function.Filenames[Expansion.FileID]);
  434. std::vector<coverage::CountedRegion> Regions;
  435. for (const auto &CR : Expansion.Function.CountedRegions)
  436. if (CR.FileID == Expansion.FileID) {
  437. Regions.push_back(CR);
  438. if (isExpansion(CR, Expansion.FileID))
  439. ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
  440. }
  441. sortNestedRegions(Regions.begin(), Regions.end());
  442. DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID
  443. << "\n");
  444. ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions);
  445. return ExpansionCoverage;
  446. }
  447. namespace {
  448. class CoverageMappingErrorCategoryType : public std::error_category {
  449. const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; }
  450. std::string message(int IE) const override {
  451. auto E = static_cast<coveragemap_error>(IE);
  452. switch (E) {
  453. case coveragemap_error::success:
  454. return "Success";
  455. case coveragemap_error::eof:
  456. return "End of File";
  457. case coveragemap_error::no_data_found:
  458. return "No coverage data found";
  459. case coveragemap_error::unsupported_version:
  460. return "Unsupported coverage format version";
  461. case coveragemap_error::truncated:
  462. return "Truncated coverage data";
  463. case coveragemap_error::malformed:
  464. return "Malformed coverage data";
  465. }
  466. llvm_unreachable("A value of coveragemap_error has no message.");
  467. }
  468. };
  469. }
  470. static ManagedStatic<CoverageMappingErrorCategoryType> ErrorCategory;
  471. const std::error_category &llvm::coveragemap_category() {
  472. return *ErrorCategory;
  473. }