GCOV.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. //===- GCOV.cpp - LLVM coverage tool --------------------------------------===//
  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. // GCOV implements the interface to read and write coverage files that use
  11. // 'gcov' format.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/Support/GCOV.h"
  15. #include "llvm/ADT/STLExtras.h"
  16. #include "llvm/Support/Debug.h"
  17. #include "llvm/Support/FileSystem.h"
  18. #include "llvm/Support/Format.h"
  19. #include "llvm/Support/MemoryObject.h"
  20. #include "llvm/Support/Path.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. #include <algorithm>
  23. #include <system_error>
  24. using namespace llvm;
  25. //===----------------------------------------------------------------------===//
  26. // GCOVFile implementation.
  27. /// readGCNO - Read GCNO buffer.
  28. bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
  29. if (!Buffer.readGCNOFormat())
  30. return false;
  31. if (!Buffer.readGCOVVersion(Version))
  32. return false;
  33. if (!Buffer.readInt(Checksum))
  34. return false;
  35. while (true) {
  36. if (!Buffer.readFunctionTag())
  37. break;
  38. auto GFun = make_unique<GCOVFunction>(*this);
  39. if (!GFun->readGCNO(Buffer, Version))
  40. return false;
  41. Functions.push_back(std::move(GFun));
  42. }
  43. GCNOInitialized = true;
  44. return true;
  45. }
  46. /// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
  47. /// called after readGCNO().
  48. bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
  49. assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
  50. if (!Buffer.readGCDAFormat())
  51. return false;
  52. GCOV::GCOVVersion GCDAVersion;
  53. if (!Buffer.readGCOVVersion(GCDAVersion))
  54. return false;
  55. if (Version != GCDAVersion) {
  56. errs() << "GCOV versions do not match.\n";
  57. return false;
  58. }
  59. uint32_t GCDAChecksum;
  60. if (!Buffer.readInt(GCDAChecksum))
  61. return false;
  62. if (Checksum != GCDAChecksum) {
  63. errs() << "File checksums do not match: " << Checksum
  64. << " != " << GCDAChecksum << ".\n";
  65. return false;
  66. }
  67. for (size_t i = 0, e = Functions.size(); i < e; ++i) {
  68. if (!Buffer.readFunctionTag()) {
  69. errs() << "Unexpected number of functions.\n";
  70. return false;
  71. }
  72. if (!Functions[i]->readGCDA(Buffer, Version))
  73. return false;
  74. }
  75. if (Buffer.readObjectTag()) {
  76. uint32_t Length;
  77. uint32_t Dummy;
  78. if (!Buffer.readInt(Length))
  79. return false;
  80. if (!Buffer.readInt(Dummy))
  81. return false; // checksum
  82. if (!Buffer.readInt(Dummy))
  83. return false; // num
  84. if (!Buffer.readInt(RunCount))
  85. return false;
  86. Buffer.advanceCursor(Length - 3);
  87. }
  88. while (Buffer.readProgramTag()) {
  89. uint32_t Length;
  90. if (!Buffer.readInt(Length))
  91. return false;
  92. Buffer.advanceCursor(Length);
  93. ++ProgramCount;
  94. }
  95. return true;
  96. }
  97. /// dump - Dump GCOVFile content to dbgs() for debugging purposes.
  98. void GCOVFile::dump() const {
  99. for (const auto &FPtr : Functions)
  100. FPtr->dump();
  101. }
  102. /// collectLineCounts - Collect line counts. This must be used after
  103. /// reading .gcno and .gcda files.
  104. void GCOVFile::collectLineCounts(FileInfo &FI) {
  105. for (const auto &FPtr : Functions)
  106. FPtr->collectLineCounts(FI);
  107. FI.setRunCount(RunCount);
  108. FI.setProgramCount(ProgramCount);
  109. }
  110. //===----------------------------------------------------------------------===//
  111. // GCOVFunction implementation.
  112. /// readGCNO - Read a function from the GCNO buffer. Return false if an error
  113. /// occurs.
  114. bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
  115. uint32_t Dummy;
  116. if (!Buff.readInt(Dummy))
  117. return false; // Function header length
  118. if (!Buff.readInt(Ident))
  119. return false;
  120. if (!Buff.readInt(Checksum))
  121. return false;
  122. if (Version != GCOV::V402) {
  123. uint32_t CfgChecksum;
  124. if (!Buff.readInt(CfgChecksum))
  125. return false;
  126. if (Parent.getChecksum() != CfgChecksum) {
  127. errs() << "File checksums do not match: " << Parent.getChecksum()
  128. << " != " << CfgChecksum << " in (" << Name << ").\n";
  129. return false;
  130. }
  131. }
  132. if (!Buff.readString(Name))
  133. return false;
  134. if (!Buff.readString(Filename))
  135. return false;
  136. if (!Buff.readInt(LineNumber))
  137. return false;
  138. // read blocks.
  139. if (!Buff.readBlockTag()) {
  140. errs() << "Block tag not found.\n";
  141. return false;
  142. }
  143. uint32_t BlockCount;
  144. if (!Buff.readInt(BlockCount))
  145. return false;
  146. for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
  147. if (!Buff.readInt(Dummy))
  148. return false; // Block flags;
  149. Blocks.push_back(make_unique<GCOVBlock>(*this, i));
  150. }
  151. // read edges.
  152. while (Buff.readEdgeTag()) {
  153. uint32_t EdgeCount;
  154. if (!Buff.readInt(EdgeCount))
  155. return false;
  156. EdgeCount = (EdgeCount - 1) / 2;
  157. uint32_t BlockNo;
  158. if (!Buff.readInt(BlockNo))
  159. return false;
  160. if (BlockNo >= BlockCount) {
  161. errs() << "Unexpected block number: " << BlockNo << " (in " << Name
  162. << ").\n";
  163. return false;
  164. }
  165. for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
  166. uint32_t Dst;
  167. if (!Buff.readInt(Dst))
  168. return false;
  169. Edges.push_back(make_unique<GCOVEdge>(*Blocks[BlockNo], *Blocks[Dst]));
  170. GCOVEdge *Edge = Edges.back().get();
  171. Blocks[BlockNo]->addDstEdge(Edge);
  172. Blocks[Dst]->addSrcEdge(Edge);
  173. if (!Buff.readInt(Dummy))
  174. return false; // Edge flag
  175. }
  176. }
  177. // read line table.
  178. while (Buff.readLineTag()) {
  179. uint32_t LineTableLength;
  180. // Read the length of this line table.
  181. if (!Buff.readInt(LineTableLength))
  182. return false;
  183. uint32_t EndPos = Buff.getCursor() + LineTableLength * 4;
  184. uint32_t BlockNo;
  185. // Read the block number this table is associated with.
  186. if (!Buff.readInt(BlockNo))
  187. return false;
  188. if (BlockNo >= BlockCount) {
  189. errs() << "Unexpected block number: " << BlockNo << " (in " << Name
  190. << ").\n";
  191. return false;
  192. }
  193. GCOVBlock &Block = *Blocks[BlockNo];
  194. // Read the word that pads the beginning of the line table. This may be a
  195. // flag of some sort, but seems to always be zero.
  196. if (!Buff.readInt(Dummy))
  197. return false;
  198. // Line information starts here and continues up until the last word.
  199. if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) {
  200. StringRef F;
  201. // Read the source file name.
  202. if (!Buff.readString(F))
  203. return false;
  204. if (Filename != F) {
  205. errs() << "Multiple sources for a single basic block: " << Filename
  206. << " != " << F << " (in " << Name << ").\n";
  207. return false;
  208. }
  209. // Read lines up to, but not including, the null terminator.
  210. while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
  211. uint32_t Line;
  212. if (!Buff.readInt(Line))
  213. return false;
  214. // Line 0 means this instruction was injected by the compiler. Skip it.
  215. if (!Line)
  216. continue;
  217. Block.addLine(Line);
  218. }
  219. // Read the null terminator.
  220. if (!Buff.readInt(Dummy))
  221. return false;
  222. }
  223. // The last word is either a flag or padding, it isn't clear which. Skip
  224. // over it.
  225. if (!Buff.readInt(Dummy))
  226. return false;
  227. }
  228. return true;
  229. }
  230. /// readGCDA - Read a function from the GCDA buffer. Return false if an error
  231. /// occurs.
  232. bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
  233. uint32_t Dummy;
  234. if (!Buff.readInt(Dummy))
  235. return false; // Function header length
  236. uint32_t GCDAIdent;
  237. if (!Buff.readInt(GCDAIdent))
  238. return false;
  239. if (Ident != GCDAIdent) {
  240. errs() << "Function identifiers do not match: " << Ident
  241. << " != " << GCDAIdent << " (in " << Name << ").\n";
  242. return false;
  243. }
  244. uint32_t GCDAChecksum;
  245. if (!Buff.readInt(GCDAChecksum))
  246. return false;
  247. if (Checksum != GCDAChecksum) {
  248. errs() << "Function checksums do not match: " << Checksum
  249. << " != " << GCDAChecksum << " (in " << Name << ").\n";
  250. return false;
  251. }
  252. uint32_t CfgChecksum;
  253. if (Version != GCOV::V402) {
  254. if (!Buff.readInt(CfgChecksum))
  255. return false;
  256. if (Parent.getChecksum() != CfgChecksum) {
  257. errs() << "File checksums do not match: " << Parent.getChecksum()
  258. << " != " << CfgChecksum << " (in " << Name << ").\n";
  259. return false;
  260. }
  261. }
  262. StringRef GCDAName;
  263. if (!Buff.readString(GCDAName))
  264. return false;
  265. if (Name != GCDAName) {
  266. errs() << "Function names do not match: " << Name << " != " << GCDAName
  267. << ".\n";
  268. return false;
  269. }
  270. if (!Buff.readArcTag()) {
  271. errs() << "Arc tag not found (in " << Name << ").\n";
  272. return false;
  273. }
  274. uint32_t Count;
  275. if (!Buff.readInt(Count))
  276. return false;
  277. Count /= 2;
  278. // This for loop adds the counts for each block. A second nested loop is
  279. // required to combine the edge counts that are contained in the GCDA file.
  280. for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
  281. // The last block is always reserved for exit block
  282. if (BlockNo >= Blocks.size()) {
  283. errs() << "Unexpected number of edges (in " << Name << ").\n";
  284. return false;
  285. }
  286. if (BlockNo == Blocks.size() - 1)
  287. errs() << "(" << Name << ") has arcs from exit block.\n";
  288. GCOVBlock &Block = *Blocks[BlockNo];
  289. for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
  290. ++EdgeNo) {
  291. if (Count == 0) {
  292. errs() << "Unexpected number of edges (in " << Name << ").\n";
  293. return false;
  294. }
  295. uint64_t ArcCount;
  296. if (!Buff.readInt64(ArcCount))
  297. return false;
  298. Block.addCount(EdgeNo, ArcCount);
  299. --Count;
  300. }
  301. Block.sortDstEdges();
  302. }
  303. return true;
  304. }
  305. /// getEntryCount - Get the number of times the function was called by
  306. /// retrieving the entry block's count.
  307. uint64_t GCOVFunction::getEntryCount() const {
  308. return Blocks.front()->getCount();
  309. }
  310. /// getExitCount - Get the number of times the function returned by retrieving
  311. /// the exit block's count.
  312. uint64_t GCOVFunction::getExitCount() const {
  313. return Blocks.back()->getCount();
  314. }
  315. /// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
  316. void GCOVFunction::dump() const {
  317. dbgs() << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
  318. << LineNumber << "\n";
  319. for (const auto &Block : Blocks)
  320. Block->dump();
  321. }
  322. /// collectLineCounts - Collect line counts. This must be used after
  323. /// reading .gcno and .gcda files.
  324. void GCOVFunction::collectLineCounts(FileInfo &FI) {
  325. // If the line number is zero, this is a function that doesn't actually appear
  326. // in the source file, so there isn't anything we can do with it.
  327. if (LineNumber == 0)
  328. return;
  329. for (const auto &Block : Blocks)
  330. Block->collectLineCounts(FI);
  331. FI.addFunctionLine(Filename, LineNumber, this);
  332. }
  333. //===----------------------------------------------------------------------===//
  334. // GCOVBlock implementation.
  335. /// ~GCOVBlock - Delete GCOVBlock and its content.
  336. GCOVBlock::~GCOVBlock() {
  337. SrcEdges.clear();
  338. DstEdges.clear();
  339. Lines.clear();
  340. }
  341. /// addCount - Add to block counter while storing the edge count. If the
  342. /// destination has no outgoing edges, also update that block's count too.
  343. void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
  344. assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
  345. DstEdges[DstEdgeNo]->Count = N;
  346. Counter += N;
  347. if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges())
  348. DstEdges[DstEdgeNo]->Dst.Counter += N;
  349. }
  350. /// sortDstEdges - Sort destination edges by block number, nop if already
  351. /// sorted. This is required for printing branch info in the correct order.
  352. void GCOVBlock::sortDstEdges() {
  353. if (!DstEdgesAreSorted) {
  354. SortDstEdgesFunctor SortEdges;
  355. std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges);
  356. }
  357. }
  358. /// collectLineCounts - Collect line counts. This must be used after
  359. /// reading .gcno and .gcda files.
  360. void GCOVBlock::collectLineCounts(FileInfo &FI) {
  361. for (uint32_t N : Lines)
  362. FI.addBlockLine(Parent.getFilename(), N, this);
  363. }
  364. /// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
  365. void GCOVBlock::dump() const {
  366. dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
  367. if (!SrcEdges.empty()) {
  368. dbgs() << "\tSource Edges : ";
  369. for (const GCOVEdge *Edge : SrcEdges)
  370. dbgs() << Edge->Src.Number << " (" << Edge->Count << "), ";
  371. dbgs() << "\n";
  372. }
  373. if (!DstEdges.empty()) {
  374. dbgs() << "\tDestination Edges : ";
  375. for (const GCOVEdge *Edge : DstEdges)
  376. dbgs() << Edge->Dst.Number << " (" << Edge->Count << "), ";
  377. dbgs() << "\n";
  378. }
  379. if (!Lines.empty()) {
  380. dbgs() << "\tLines : ";
  381. for (uint32_t N : Lines)
  382. dbgs() << (N) << ",";
  383. dbgs() << "\n";
  384. }
  385. }
  386. //===----------------------------------------------------------------------===//
  387. // FileInfo implementation.
  388. // Safe integer division, returns 0 if numerator is 0.
  389. static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
  390. if (!Numerator)
  391. return 0;
  392. return Numerator / Divisor;
  393. }
  394. // This custom division function mimics gcov's branch ouputs:
  395. // - Round to closest whole number
  396. // - Only output 0% or 100% if it's exactly that value
  397. static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
  398. if (!Numerator)
  399. return 0;
  400. if (Numerator == Divisor)
  401. return 100;
  402. uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
  403. if (Res == 0)
  404. return 1;
  405. if (Res == 100)
  406. return 99;
  407. return Res;
  408. }
  409. namespace {
  410. struct formatBranchInfo {
  411. formatBranchInfo(const GCOVOptions &Options, uint64_t Count, uint64_t Total)
  412. : Options(Options), Count(Count), Total(Total) {}
  413. void print(raw_ostream &OS) const {
  414. if (!Total)
  415. OS << "never executed";
  416. else if (Options.BranchCount)
  417. OS << "taken " << Count;
  418. else
  419. OS << "taken " << branchDiv(Count, Total) << "%";
  420. }
  421. const GCOVOptions &Options;
  422. uint64_t Count;
  423. uint64_t Total;
  424. };
  425. static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
  426. FBI.print(OS);
  427. return OS;
  428. }
  429. class LineConsumer {
  430. std::unique_ptr<MemoryBuffer> Buffer;
  431. StringRef Remaining;
  432. public:
  433. LineConsumer(StringRef Filename) {
  434. ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
  435. MemoryBuffer::getFileOrSTDIN(Filename);
  436. if (std::error_code EC = BufferOrErr.getError()) {
  437. errs() << Filename << ": " << EC.message() << "\n";
  438. Remaining = "";
  439. } else {
  440. Buffer = std::move(BufferOrErr.get());
  441. Remaining = Buffer->getBuffer();
  442. }
  443. }
  444. bool empty() { return Remaining.empty(); }
  445. void printNext(raw_ostream &OS, uint32_t LineNum) {
  446. StringRef Line;
  447. if (empty())
  448. Line = "/*EOF*/";
  449. else
  450. std::tie(Line, Remaining) = Remaining.split("\n");
  451. OS << format("%5u:", LineNum) << Line << "\n";
  452. }
  453. };
  454. }
  455. /// Convert a path to a gcov filename. If PreservePaths is true, this
  456. /// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
  457. static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
  458. if (!PreservePaths)
  459. return sys::path::filename(Filename).str();
  460. // This behaviour is defined by gcov in terms of text replacements, so it's
  461. // not likely to do anything useful on filesystems with different textual
  462. // conventions.
  463. llvm::SmallString<256> Result("");
  464. StringRef::iterator I, S, E;
  465. for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
  466. if (*I != '/')
  467. continue;
  468. if (I - S == 1 && *S == '.') {
  469. // ".", the current directory, is skipped.
  470. } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
  471. // "..", the parent directory, is replaced with "^".
  472. Result.append("^#");
  473. } else {
  474. if (S < I)
  475. // Leave other components intact,
  476. Result.append(S, I);
  477. // And separate with "#".
  478. Result.push_back('#');
  479. }
  480. S = I + 1;
  481. }
  482. if (S < I)
  483. Result.append(S, I);
  484. return Result.str();
  485. }
  486. std::string FileInfo::getCoveragePath(StringRef Filename,
  487. StringRef MainFilename) {
  488. if (Options.NoOutput)
  489. // This is probably a bug in gcov, but when -n is specified, paths aren't
  490. // mangled at all, and the -l and -p options are ignored. Here, we do the
  491. // same.
  492. return Filename;
  493. std::string CoveragePath;
  494. if (Options.LongFileNames && !Filename.equals(MainFilename))
  495. CoveragePath =
  496. mangleCoveragePath(MainFilename, Options.PreservePaths) + "##";
  497. CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov";
  498. return CoveragePath;
  499. }
  500. std::unique_ptr<raw_ostream>
  501. FileInfo::openCoveragePath(StringRef CoveragePath) {
  502. if (Options.NoOutput)
  503. return llvm::make_unique<raw_null_ostream>();
  504. std::error_code EC;
  505. auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath, EC,
  506. sys::fs::F_Text);
  507. if (EC) {
  508. errs() << EC.message() << "\n";
  509. return llvm::make_unique<raw_null_ostream>();
  510. }
  511. return std::move(OS);
  512. }
  513. /// print - Print source files with collected line count information.
  514. void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
  515. StringRef GCNOFile, StringRef GCDAFile) {
  516. for (const auto &LI : LineInfo) {
  517. StringRef Filename = LI.first();
  518. auto AllLines = LineConsumer(Filename);
  519. std::string CoveragePath = getCoveragePath(Filename, MainFilename);
  520. std::unique_ptr<raw_ostream> CovStream = openCoveragePath(CoveragePath);
  521. raw_ostream &CovOS = *CovStream;
  522. CovOS << " -: 0:Source:" << Filename << "\n";
  523. CovOS << " -: 0:Graph:" << GCNOFile << "\n";
  524. CovOS << " -: 0:Data:" << GCDAFile << "\n";
  525. CovOS << " -: 0:Runs:" << RunCount << "\n";
  526. CovOS << " -: 0:Programs:" << ProgramCount << "\n";
  527. const LineData &Line = LI.second;
  528. GCOVCoverage FileCoverage(Filename);
  529. for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty();
  530. ++LineIndex) {
  531. if (Options.BranchInfo) {
  532. FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
  533. if (FuncsIt != Line.Functions.end())
  534. printFunctionSummary(CovOS, FuncsIt->second);
  535. }
  536. BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
  537. if (BlocksIt == Line.Blocks.end()) {
  538. // No basic blocks are on this line. Not an executable line of code.
  539. CovOS << " -:";
  540. AllLines.printNext(CovOS, LineIndex + 1);
  541. } else {
  542. const BlockVector &Blocks = BlocksIt->second;
  543. // Add up the block counts to form line counts.
  544. DenseMap<const GCOVFunction *, bool> LineExecs;
  545. uint64_t LineCount = 0;
  546. for (const GCOVBlock *Block : Blocks) {
  547. if (Options.AllBlocks) {
  548. // Only take the highest block count for that line.
  549. uint64_t BlockCount = Block->getCount();
  550. LineCount = LineCount > BlockCount ? LineCount : BlockCount;
  551. } else {
  552. // Sum up all of the block counts.
  553. LineCount += Block->getCount();
  554. }
  555. if (Options.FuncCoverage) {
  556. // This is a slightly convoluted way to most accurately gather line
  557. // statistics for functions. Basically what is happening is that we
  558. // don't want to count a single line with multiple blocks more than
  559. // once. However, we also don't simply want to give the total line
  560. // count to every function that starts on the line. Thus, what is
  561. // happening here are two things:
  562. // 1) Ensure that the number of logical lines is only incremented
  563. // once per function.
  564. // 2) If there are multiple blocks on the same line, ensure that the
  565. // number of lines executed is incremented as long as at least
  566. // one of the blocks are executed.
  567. const GCOVFunction *Function = &Block->getParent();
  568. if (FuncCoverages.find(Function) == FuncCoverages.end()) {
  569. std::pair<const GCOVFunction *, GCOVCoverage> KeyValue(
  570. Function, GCOVCoverage(Function->getName()));
  571. FuncCoverages.insert(KeyValue);
  572. }
  573. GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
  574. if (LineExecs.find(Function) == LineExecs.end()) {
  575. if (Block->getCount()) {
  576. ++FuncCoverage.LinesExec;
  577. LineExecs[Function] = true;
  578. } else {
  579. LineExecs[Function] = false;
  580. }
  581. ++FuncCoverage.LogicalLines;
  582. } else if (!LineExecs[Function] && Block->getCount()) {
  583. ++FuncCoverage.LinesExec;
  584. LineExecs[Function] = true;
  585. }
  586. }
  587. }
  588. if (LineCount == 0)
  589. CovOS << " #####:";
  590. else {
  591. CovOS << format("%9" PRIu64 ":", LineCount);
  592. ++FileCoverage.LinesExec;
  593. }
  594. ++FileCoverage.LogicalLines;
  595. AllLines.printNext(CovOS, LineIndex + 1);
  596. uint32_t BlockNo = 0;
  597. uint32_t EdgeNo = 0;
  598. for (const GCOVBlock *Block : Blocks) {
  599. // Only print block and branch information at the end of the block.
  600. if (Block->getLastLine() != LineIndex + 1)
  601. continue;
  602. if (Options.AllBlocks)
  603. printBlockInfo(CovOS, *Block, LineIndex, BlockNo);
  604. if (Options.BranchInfo) {
  605. size_t NumEdges = Block->getNumDstEdges();
  606. if (NumEdges > 1)
  607. printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
  608. else if (Options.UncondBranch && NumEdges == 1)
  609. printUncondBranchInfo(CovOS, EdgeNo,
  610. (*Block->dst_begin())->Count);
  611. }
  612. }
  613. }
  614. }
  615. FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
  616. }
  617. // FIXME: There is no way to detect calls given current instrumentation.
  618. if (Options.FuncCoverage)
  619. printFuncCoverage(InfoOS);
  620. printFileCoverage(InfoOS);
  621. return;
  622. }
  623. /// printFunctionSummary - Print function and block summary.
  624. void FileInfo::printFunctionSummary(raw_ostream &OS,
  625. const FunctionVector &Funcs) const {
  626. for (const GCOVFunction *Func : Funcs) {
  627. uint64_t EntryCount = Func->getEntryCount();
  628. uint32_t BlocksExec = 0;
  629. for (const GCOVBlock &Block : Func->blocks())
  630. if (Block.getNumDstEdges() && Block.getCount())
  631. ++BlocksExec;
  632. OS << "function " << Func->getName() << " called " << EntryCount
  633. << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount)
  634. << "% blocks executed "
  635. << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n";
  636. }
  637. }
  638. /// printBlockInfo - Output counts for each block.
  639. void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
  640. uint32_t LineIndex, uint32_t &BlockNo) const {
  641. if (Block.getCount() == 0)
  642. OS << " $$$$$:";
  643. else
  644. OS << format("%9" PRIu64 ":", Block.getCount());
  645. OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++);
  646. }
  647. /// printBranchInfo - Print conditional branch probabilities.
  648. void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
  649. GCOVCoverage &Coverage, uint32_t &EdgeNo) {
  650. SmallVector<uint64_t, 16> BranchCounts;
  651. uint64_t TotalCounts = 0;
  652. for (const GCOVEdge *Edge : Block.dsts()) {
  653. BranchCounts.push_back(Edge->Count);
  654. TotalCounts += Edge->Count;
  655. if (Block.getCount())
  656. ++Coverage.BranchesExec;
  657. if (Edge->Count)
  658. ++Coverage.BranchesTaken;
  659. ++Coverage.Branches;
  660. if (Options.FuncCoverage) {
  661. const GCOVFunction *Function = &Block.getParent();
  662. GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
  663. if (Block.getCount())
  664. ++FuncCoverage.BranchesExec;
  665. if (Edge->Count)
  666. ++FuncCoverage.BranchesTaken;
  667. ++FuncCoverage.Branches;
  668. }
  669. }
  670. for (uint64_t N : BranchCounts)
  671. OS << format("branch %2u ", EdgeNo++)
  672. << formatBranchInfo(Options, N, TotalCounts) << "\n";
  673. }
  674. /// printUncondBranchInfo - Print unconditional branch probabilities.
  675. void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
  676. uint64_t Count) const {
  677. OS << format("unconditional %2u ", EdgeNo++)
  678. << formatBranchInfo(Options, Count, Count) << "\n";
  679. }
  680. // printCoverage - Print generic coverage info used by both printFuncCoverage
  681. // and printFileCoverage.
  682. void FileInfo::printCoverage(raw_ostream &OS,
  683. const GCOVCoverage &Coverage) const {
  684. OS << format("Lines executed:%.2f%% of %u\n",
  685. double(Coverage.LinesExec) * 100 / Coverage.LogicalLines,
  686. Coverage.LogicalLines);
  687. if (Options.BranchInfo) {
  688. if (Coverage.Branches) {
  689. OS << format("Branches executed:%.2f%% of %u\n",
  690. double(Coverage.BranchesExec) * 100 / Coverage.Branches,
  691. Coverage.Branches);
  692. OS << format("Taken at least once:%.2f%% of %u\n",
  693. double(Coverage.BranchesTaken) * 100 / Coverage.Branches,
  694. Coverage.Branches);
  695. } else {
  696. OS << "No branches\n";
  697. }
  698. OS << "No calls\n"; // to be consistent with gcov
  699. }
  700. }
  701. // printFuncCoverage - Print per-function coverage info.
  702. void FileInfo::printFuncCoverage(raw_ostream &OS) const {
  703. for (const auto &FC : FuncCoverages) {
  704. const GCOVCoverage &Coverage = FC.second;
  705. OS << "Function '" << Coverage.Name << "'\n";
  706. printCoverage(OS, Coverage);
  707. OS << "\n";
  708. }
  709. }
  710. // printFileCoverage - Print per-file coverage info.
  711. void FileInfo::printFileCoverage(raw_ostream &OS) const {
  712. for (const auto &FC : FileCoverages) {
  713. const std::string &Filename = FC.first;
  714. const GCOVCoverage &Coverage = FC.second;
  715. OS << "File '" << Coverage.Name << "'\n";
  716. printCoverage(OS, Coverage);
  717. if (!Options.NoOutput)
  718. OS << Coverage.Name << ":creating '" << Filename << "'\n";
  719. OS << "\n";
  720. }
  721. }