blob: 62cbc5ef03e47df4d89e332dff2d6100b2fe9203 [file] [log] [blame]
Yuchen Wuc3e64242013-12-05 22:02:29 +00001//===- GCOV.cpp - LLVM coverage tool --------------------------------------===//
Devang Patel37140652011-09-28 18:50:00 +00002//
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//
NAKAMURA Takumi3b551962013-11-14 11:44:58 +000010// GCOV implements the interface to read and write coverage files that use
Devang Patel8dfb6552011-10-04 17:24:48 +000011// 'gcov' format.
Devang Patel37140652011-09-28 18:50:00 +000012//
Devang Patel37140652011-09-28 18:50:00 +000013//===----------------------------------------------------------------------===//
14
Yuchen Wu03678152013-10-25 02:22:24 +000015#include "llvm/Support/Debug.h"
Devang Patel8dfb6552011-10-04 17:24:48 +000016#include "llvm/Support/GCOV.h"
Devang Patel37140652011-09-28 18:50:00 +000017#include "llvm/ADT/OwningPtr.h"
Devang Patela9e8a252011-09-29 16:46:47 +000018#include "llvm/ADT/STLExtras.h"
Bob Wilson3461bed2013-10-22 05:09:41 +000019#include "llvm/Support/Format.h"
Devang Patel37140652011-09-28 18:50:00 +000020#include "llvm/Support/MemoryObject.h"
21#include "llvm/Support/system_error.h"
Yuchen Wu342714c2013-12-13 01:15:07 +000022#include <algorithm>
Devang Patel37140652011-09-28 18:50:00 +000023using namespace llvm;
24
25//===----------------------------------------------------------------------===//
26// GCOVFile implementation.
27
28/// ~GCOVFile - Delete GCOVFile and its content.
29GCOVFile::~GCOVFile() {
30 DeleteContainerPointers(Functions);
31}
32
Yuchen Wubec4e902013-12-04 04:49:23 +000033/// readGCNO - Read GCNO buffer.
34bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
35 if (!Buffer.readGCNOFormat()) return false;
36 if (!Buffer.readGCOVVersion(Version)) return false;
37
38 if (!Buffer.readInt(Checksum)) return false;
39 while (true) {
40 if (!Buffer.readFunctionTag()) break;
Yuchen Wu57529972013-12-04 05:42:28 +000041 GCOVFunction *GFun = new GCOVFunction(*this);
Yuchen Wubec4e902013-12-04 04:49:23 +000042 if (!GFun->readGCNO(Buffer, Version))
43 return false;
44 Functions.push_back(GFun);
45 }
46
Yuchen Wu21517e42013-12-04 05:07:36 +000047 GCNOInitialized = true;
Yuchen Wubec4e902013-12-04 04:49:23 +000048 return true;
Devang Patele5a8f2f92011-09-29 17:06:40 +000049}
50
Yuchen Wubec4e902013-12-04 04:49:23 +000051/// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
52/// called after readGCNO().
53bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
Yuchen Wu21517e42013-12-04 05:07:36 +000054 assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
Yuchen Wubec4e902013-12-04 04:49:23 +000055 if (!Buffer.readGCDAFormat()) return false;
56 GCOV::GCOVVersion GCDAVersion;
57 if (!Buffer.readGCOVVersion(GCDAVersion)) return false;
58 if (Version != GCDAVersion) {
59 errs() << "GCOV versions do not match.\n";
Devang Patel37140652011-09-28 18:50:00 +000060 return false;
Yuchen Wubec4e902013-12-04 04:49:23 +000061 }
Devang Patel37140652011-09-28 18:50:00 +000062
Yuchen Wubec4e902013-12-04 04:49:23 +000063 uint32_t GCDAChecksum;
64 if (!Buffer.readInt(GCDAChecksum)) return false;
65 if (Checksum != GCDAChecksum) {
Yuchen Wu57529972013-12-04 05:42:28 +000066 errs() << "File checksums do not match: " << Checksum << " != "
67 << GCDAChecksum << ".\n";
Yuchen Wubec4e902013-12-04 04:49:23 +000068 return false;
69 }
70 for (size_t i = 0, e = Functions.size(); i < e; ++i) {
71 if (!Buffer.readFunctionTag()) {
72 errs() << "Unexpected number of functions.\n";
Yuchen Wubabe7492013-11-20 04:15:05 +000073 return false;
74 }
Yuchen Wubec4e902013-12-04 04:49:23 +000075 if (!Functions[i]->readGCDA(Buffer, Version))
76 return false;
77 }
78 if (Buffer.readObjectTag()) {
79 uint32_t Length;
80 uint32_t Dummy;
81 if (!Buffer.readInt(Length)) return false;
82 if (!Buffer.readInt(Dummy)) return false; // checksum
83 if (!Buffer.readInt(Dummy)) return false; // num
Yuchen Wu8742a282013-12-16 20:03:11 +000084 if (!Buffer.readInt(RunCount)) return false;
Yuchen Wubec4e902013-12-04 04:49:23 +000085 Buffer.advanceCursor(Length-3);
86 }
87 while (Buffer.readProgramTag()) {
88 uint32_t Length;
89 if (!Buffer.readInt(Length)) return false;
90 Buffer.advanceCursor(Length);
91 ++ProgramCount;
Yuchen Wu14ae8e62013-10-25 02:22:21 +000092 }
93
Devang Patel37140652011-09-28 18:50:00 +000094 return true;
95}
96
Yuchen Wu03678152013-10-25 02:22:24 +000097/// dump - Dump GCOVFile content to dbgs() for debugging purposes.
Yuchen Wuef6909d2013-11-19 20:33:32 +000098void GCOVFile::dump() const {
99 for (SmallVectorImpl<GCOVFunction *>::const_iterator I = Functions.begin(),
Bill Wendlingea6397f2012-07-19 00:11:40 +0000100 E = Functions.end(); I != E; ++I)
Devang Patel37140652011-09-28 18:50:00 +0000101 (*I)->dump();
102}
103
104/// collectLineCounts - Collect line counts. This must be used after
105/// reading .gcno and .gcda files.
106void GCOVFile::collectLineCounts(FileInfo &FI) {
Craig Topperaf0dea12013-07-04 01:31:24 +0000107 for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(),
NAKAMURA Takumi3b551962013-11-14 11:44:58 +0000108 E = Functions.end(); I != E; ++I)
Devang Patel37140652011-09-28 18:50:00 +0000109 (*I)->collectLineCounts(FI);
Yuchen Wu30672d92013-11-05 01:11:58 +0000110 FI.setRunCount(RunCount);
Yuchen Wu14ae8e62013-10-25 02:22:21 +0000111 FI.setProgramCount(ProgramCount);
Devang Patel37140652011-09-28 18:50:00 +0000112}
113
114//===----------------------------------------------------------------------===//
115// GCOVFunction implementation.
116
117/// ~GCOVFunction - Delete GCOVFunction and its content.
118GCOVFunction::~GCOVFunction() {
119 DeleteContainerPointers(Blocks);
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000120 DeleteContainerPointers(Edges);
Devang Patel37140652011-09-28 18:50:00 +0000121}
122
Yuchen Wuba718332013-12-03 00:15:49 +0000123/// readGCNO - Read a function from the GCNO buffer. Return false if an error
124/// occurs.
Yuchen Wubec4e902013-12-04 04:49:23 +0000125bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
Yuchen Wue28da842013-11-14 00:07:15 +0000126 uint32_t Dummy;
127 if (!Buff.readInt(Dummy)) return false; // Function header length
128 if (!Buff.readInt(Ident)) return false;
Daniel Jasper87a24d52013-12-04 08:57:17 +0000129 if (!Buff.readInt(Checksum)) return false;
Yuchen Wu57529972013-12-04 05:42:28 +0000130 if (Version != GCOV::V402) {
131 uint32_t CfgChecksum;
132 if (!Buff.readInt(CfgChecksum)) return false;
133 if (Parent.getChecksum() != CfgChecksum) {
134 errs() << "File checksums do not match: " << Parent.getChecksum()
135 << " != " << CfgChecksum << " in (" << Name << ").\n";
136 return false;
137 }
138 }
Yuchen Wue28da842013-11-14 00:07:15 +0000139 if (!Buff.readString(Name)) return false;
Yuchen Wuba718332013-12-03 00:15:49 +0000140 if (!Buff.readString(Filename)) return false;
Yuchen Wue28da842013-11-14 00:07:15 +0000141 if (!Buff.readInt(LineNumber)) return false;
Devang Patel37140652011-09-28 18:50:00 +0000142
143 // read blocks.
Yuchen Wue28da842013-11-14 00:07:15 +0000144 if (!Buff.readBlockTag()) {
145 errs() << "Block tag not found.\n";
146 return false;
147 }
148 uint32_t BlockCount;
149 if (!Buff.readInt(BlockCount)) return false;
Bob Wilson868e6e32013-10-22 20:02:36 +0000150 for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
Yuchen Wue28da842013-11-14 00:07:15 +0000151 if (!Buff.readInt(Dummy)) return false; // Block flags;
Yuchen Wud738bee2013-11-14 00:32:00 +0000152 Blocks.push_back(new GCOVBlock(*this, i));
Devang Patel37140652011-09-28 18:50:00 +0000153 }
154
155 // read edges.
156 while (Buff.readEdgeTag()) {
Yuchen Wue28da842013-11-14 00:07:15 +0000157 uint32_t EdgeCount;
158 if (!Buff.readInt(EdgeCount)) return false;
159 EdgeCount = (EdgeCount - 1) / 2;
160 uint32_t BlockNo;
161 if (!Buff.readInt(BlockNo)) return false;
162 if (BlockNo >= BlockCount) {
Yuchen Wu4c9f19d2013-12-05 22:02:33 +0000163 errs() << "Unexpected block number: " << BlockNo << " (in " << Name
164 << ").\n";
Yuchen Wue28da842013-11-14 00:07:15 +0000165 return false;
166 }
Bob Wilson868e6e32013-10-22 20:02:36 +0000167 for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
Yuchen Wue28da842013-11-14 00:07:15 +0000168 uint32_t Dst;
169 if (!Buff.readInt(Dst)) return false;
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000170 GCOVEdge *Edge = new GCOVEdge(Blocks[BlockNo], Blocks[Dst]);
171 Edges.push_back(Edge);
172 Blocks[BlockNo]->addDstEdge(Edge);
173 Blocks[Dst]->addSrcEdge(Edge);
Yuchen Wue28da842013-11-14 00:07:15 +0000174 if (!Buff.readInt(Dummy)) return false; // Edge flag
Devang Patel37140652011-09-28 18:50:00 +0000175 }
176 }
177
178 // read line table.
179 while (Buff.readLineTag()) {
Yuchen Wue28da842013-11-14 00:07:15 +0000180 uint32_t LineTableLength;
181 if (!Buff.readInt(LineTableLength)) return false;
Bob Wilson00928bc2013-10-22 19:54:32 +0000182 uint32_t EndPos = Buff.getCursor() + LineTableLength*4;
Yuchen Wue28da842013-11-14 00:07:15 +0000183 uint32_t BlockNo;
184 if (!Buff.readInt(BlockNo)) return false;
185 if (BlockNo >= BlockCount) {
Yuchen Wu4c9f19d2013-12-05 22:02:33 +0000186 errs() << "Unexpected block number: " << BlockNo << " (in " << Name
187 << ").\n";
Yuchen Wue28da842013-11-14 00:07:15 +0000188 return false;
Devang Patel37140652011-09-28 18:50:00 +0000189 }
Yuchen Wue28da842013-11-14 00:07:15 +0000190 GCOVBlock *Block = Blocks[BlockNo];
191 if (!Buff.readInt(Dummy)) return false; // flag
192 while (Buff.getCursor() != (EndPos - 4)) {
Yuchen Wud738bee2013-11-14 00:32:00 +0000193 StringRef F;
194 if (!Buff.readString(F)) return false;
Yuchen Wu4c9f19d2013-12-05 22:02:33 +0000195 if (Filename != F) {
196 errs() << "Multiple sources for a single basic block: " << Filename
197 << " != " << F << " (in " << Name << ").\n";
Yuchen Wud738bee2013-11-14 00:32:00 +0000198 return false;
199 }
Yuchen Wue28da842013-11-14 00:07:15 +0000200 if (Buff.getCursor() == (EndPos - 4)) break;
201 while (true) {
202 uint32_t Line;
203 if (!Buff.readInt(Line)) return false;
204 if (!Line) break;
Yuchen Wud738bee2013-11-14 00:32:00 +0000205 Block->addLine(Line);
Yuchen Wue28da842013-11-14 00:07:15 +0000206 }
207 }
208 if (!Buff.readInt(Dummy)) return false; // flag
Devang Patel37140652011-09-28 18:50:00 +0000209 }
210 return true;
211}
212
Yuchen Wuba718332013-12-03 00:15:49 +0000213/// readGCDA - Read a function from the GCDA buffer. Return false if an error
214/// occurs.
Yuchen Wubec4e902013-12-04 04:49:23 +0000215bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
Yuchen Wuba718332013-12-03 00:15:49 +0000216 uint32_t Dummy;
217 if (!Buff.readInt(Dummy)) return false; // Function header length
Daniel Jasper87a24d52013-12-04 08:57:17 +0000218
Yuchen Wu57529972013-12-04 05:42:28 +0000219 uint32_t GCDAIdent;
220 if (!Buff.readInt(GCDAIdent)) return false;
221 if (Ident != GCDAIdent) {
222 errs() << "Function identifiers do not match: " << Ident << " != "
223 << GCDAIdent << " (in " << Name << ").\n";
224 return false;
225 }
Yuchen Wuba718332013-12-03 00:15:49 +0000226
Daniel Jasper87a24d52013-12-04 08:57:17 +0000227 uint32_t GCDAChecksum;
228 if (!Buff.readInt(GCDAChecksum)) return false;
229 if (Checksum != GCDAChecksum) {
230 errs() << "Function checksums do not match: " << Checksum << " != "
231 << GCDAChecksum << " (in " << Name << ").\n";
232 return false;
233 }
Yuchen Wu57529972013-12-04 05:42:28 +0000234
235 uint32_t CfgChecksum;
236 if (Version != GCOV::V402) {
237 if (!Buff.readInt(CfgChecksum)) return false;
238 if (Parent.getChecksum() != CfgChecksum) {
239 errs() << "File checksums do not match: " << Parent.getChecksum()
240 << " != " << CfgChecksum << " (in " << Name << ").\n";
241 return false;
242 }
243 }
244
245 StringRef GCDAName;
246 if (!Buff.readString(GCDAName)) return false;
247 if (Name != GCDAName) {
248 errs() << "Function names do not match: " << Name << " != " << GCDAName
249 << ".\n";
250 return false;
251 }
Yuchen Wuba718332013-12-03 00:15:49 +0000252
253 if (!Buff.readArcTag()) {
Yuchen Wu57529972013-12-04 05:42:28 +0000254 errs() << "Arc tag not found (in " << Name << ").\n";
Yuchen Wuba718332013-12-03 00:15:49 +0000255 return false;
256 }
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000257
Yuchen Wuba718332013-12-03 00:15:49 +0000258 uint32_t Count;
259 if (!Buff.readInt(Count)) return false;
260 Count /= 2;
261
262 // This for loop adds the counts for each block. A second nested loop is
263 // required to combine the edge counts that are contained in the GCDA file.
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000264 for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
265 // The last block is always reserved for exit block
266 if (BlockNo >= Blocks.size()-1) {
Yuchen Wu57529972013-12-04 05:42:28 +0000267 errs() << "Unexpected number of edges (in " << Name << ").\n";
Yuchen Wuba718332013-12-03 00:15:49 +0000268 return false;
269 }
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000270 GCOVBlock &Block = *Blocks[BlockNo];
271 for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
272 ++EdgeNo) {
Yuchen Wuba718332013-12-03 00:15:49 +0000273 if (Count == 0) {
Yuchen Wu57529972013-12-04 05:42:28 +0000274 errs() << "Unexpected number of edges (in " << Name << ").\n";
Yuchen Wuba718332013-12-03 00:15:49 +0000275 return false;
276 }
277 uint64_t ArcCount;
278 if (!Buff.readInt64(ArcCount)) return false;
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000279 Block.addCount(EdgeNo, ArcCount);
Yuchen Wuba718332013-12-03 00:15:49 +0000280 --Count;
281 }
Yuchen Wu342714c2013-12-13 01:15:07 +0000282 Block.sortDstEdges();
Yuchen Wuba718332013-12-03 00:15:49 +0000283 }
284 return true;
285}
286
Yuchen Wu342714c2013-12-13 01:15:07 +0000287/// getEntryCount - Get the number of times the function was called by
288/// retrieving the entry block's count.
289uint64_t GCOVFunction::getEntryCount() const {
290 return Blocks.front()->getCount();
291}
292
293/// getExitCount - Get the number of times the function returned by retrieving
294/// the exit block's count.
295uint64_t GCOVFunction::getExitCount() const {
296 return Blocks.back()->getCount();
297}
298
Yuchen Wu03678152013-10-25 02:22:24 +0000299/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
Yuchen Wuef6909d2013-11-19 20:33:32 +0000300void GCOVFunction::dump() const {
Yuchen Wu03678152013-10-25 02:22:24 +0000301 dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
Yuchen Wuef6909d2013-11-19 20:33:32 +0000302 for (SmallVectorImpl<GCOVBlock *>::const_iterator I = Blocks.begin(),
Bill Wendlingea6397f2012-07-19 00:11:40 +0000303 E = Blocks.end(); I != E; ++I)
Devang Patel37140652011-09-28 18:50:00 +0000304 (*I)->dump();
305}
306
307/// collectLineCounts - Collect line counts. This must be used after
308/// reading .gcno and .gcda files.
309void GCOVFunction::collectLineCounts(FileInfo &FI) {
Craig Topperaf0dea12013-07-04 01:31:24 +0000310 for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(),
Bill Wendlingea6397f2012-07-19 00:11:40 +0000311 E = Blocks.end(); I != E; ++I)
Devang Patel37140652011-09-28 18:50:00 +0000312 (*I)->collectLineCounts(FI);
Yuchen Wu342714c2013-12-13 01:15:07 +0000313 FI.addFunctionLine(Filename, LineNumber, this);
Devang Patel37140652011-09-28 18:50:00 +0000314}
315
316//===----------------------------------------------------------------------===//
317// GCOVBlock implementation.
318
319/// ~GCOVBlock - Delete GCOVBlock and its content.
320GCOVBlock::~GCOVBlock() {
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000321 SrcEdges.clear();
322 DstEdges.clear();
Yuchen Wud738bee2013-11-14 00:32:00 +0000323 Lines.clear();
Devang Patel37140652011-09-28 18:50:00 +0000324}
325
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000326/// addCount - Add to block counter while storing the edge count. If the
327/// destination has no outgoing edges, also update that block's count too.
328void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
329 assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
330 DstEdges[DstEdgeNo]->Count = N;
331 Counter += N;
332 if (!DstEdges[DstEdgeNo]->Dst->getNumDstEdges())
333 DstEdges[DstEdgeNo]->Dst->Counter += N;
334}
335
Yuchen Wu342714c2013-12-13 01:15:07 +0000336/// sortDstEdges - Sort destination edges by block number, nop if already
337/// sorted. This is required for printing branch info in the correct order.
338void GCOVBlock::sortDstEdges() {
339 if (!DstEdgesAreSorted) {
340 SortDstEdgesFunctor SortEdges;
341 std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges);
342 }
343}
344
Devang Patel37140652011-09-28 18:50:00 +0000345/// collectLineCounts - Collect line counts. This must be used after
346/// reading .gcno and .gcda files.
347void GCOVBlock::collectLineCounts(FileInfo &FI) {
Yuchen Wud738bee2013-11-14 00:32:00 +0000348 for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
Bill Wendlingea6397f2012-07-19 00:11:40 +0000349 E = Lines.end(); I != E; ++I)
Yuchen Wu8f1c8812013-12-03 00:38:21 +0000350 FI.addBlockLine(Parent.getFilename(), *I, this);
Devang Patel37140652011-09-28 18:50:00 +0000351}
352
Yuchen Wu03678152013-10-25 02:22:24 +0000353/// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
Yuchen Wuef6909d2013-11-19 20:33:32 +0000354void GCOVBlock::dump() const {
Yuchen Wu03678152013-10-25 02:22:24 +0000355 dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
Yuchen Wu8ad9b042013-12-03 00:24:44 +0000356 if (!SrcEdges.empty()) {
357 dbgs() << "\tSource Edges : ";
358 for (EdgeIterator I = SrcEdges.begin(), E = SrcEdges.end(); I != E; ++I) {
359 const GCOVEdge *Edge = *I;
360 dbgs() << Edge->Src->Number << " (" << Edge->Count << "), ";
361 }
362 dbgs() << "\n";
363 }
364 if (!DstEdges.empty()) {
365 dbgs() << "\tDestination Edges : ";
366 for (EdgeIterator I = DstEdges.begin(), E = DstEdges.end(); I != E; ++I) {
367 const GCOVEdge *Edge = *I;
368 dbgs() << Edge->Dst->Number << " (" << Edge->Count << "), ";
369 }
Yuchen Wu03678152013-10-25 02:22:24 +0000370 dbgs() << "\n";
Devang Patel37140652011-09-28 18:50:00 +0000371 }
372 if (!Lines.empty()) {
Yuchen Wu03678152013-10-25 02:22:24 +0000373 dbgs() << "\tLines : ";
Yuchen Wuef6909d2013-11-19 20:33:32 +0000374 for (SmallVectorImpl<uint32_t>::const_iterator I = Lines.begin(),
Yuchen Wud738bee2013-11-14 00:32:00 +0000375 E = Lines.end(); I != E; ++I)
376 dbgs() << (*I) << ",";
377 dbgs() << "\n";
Devang Patel37140652011-09-28 18:50:00 +0000378 }
379}
380
381//===----------------------------------------------------------------------===//
Devang Patel37140652011-09-28 18:50:00 +0000382// FileInfo implementation.
383
Yuchen Wu342714c2013-12-13 01:15:07 +0000384// Safe integer division, returns 0 if numerator is 0.
385static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
386 if (!Numerator)
387 return 0;
388 return Numerator/Divisor;
389}
390
391// This custom division function mimics gcov's branch ouputs:
392// - Round to closest whole number
393// - Only output 0% or 100% if it's exactly that value
394static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
395 if (!Numerator)
396 return 0;
397 if (Numerator == Divisor)
398 return 100;
399
400 uint8_t Res = (Numerator*100+Divisor/2) / Divisor;
401 if (Res == 0)
402 return 1;
403 if (Res == 100)
404 return 99;
405 return Res;
406}
407
Yuchen Wu73dc3812013-12-18 18:40:15 +0000408struct formatBranchInfo {
409 formatBranchInfo(const GCOVOptions &Options, uint64_t Count,
410 uint64_t Total) :
411 Options(Options), Count(Count), Total(Total) {}
412
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
422 const GCOVOptions &Options;
423 uint64_t Count;
424 uint64_t Total;
425};
426
427static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
428 FBI.print(OS);
429 return OS;
430}
431
Devang Patel37140652011-09-28 18:50:00 +0000432/// print - Print source files with collected line count information.
Yuchen Wu342714c2013-12-13 01:15:07 +0000433void FileInfo::print(StringRef GCNOFile, StringRef GCDAFile) const {
Yuchen Wu8f1c8812013-12-03 00:38:21 +0000434 for (StringMap<LineData>::const_iterator I = LineInfo.begin(),
Yuchen Wuef6909d2013-11-19 20:33:32 +0000435 E = LineInfo.end(); I != E; ++I) {
Devang Patel37140652011-09-28 18:50:00 +0000436 StringRef Filename = I->first();
Devang Patel37140652011-09-28 18:50:00 +0000437 OwningPtr<MemoryBuffer> Buff;
438 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
439 errs() << Filename << ": " << ec.message() << "\n";
440 return;
441 }
Benjamin Kramer67421c12013-11-15 09:44:17 +0000442 StringRef AllLines = Buff->getBuffer();
Yuchen Wu8aac4f62013-11-19 20:57:20 +0000443
Yuchen Wu9af39382013-12-05 20:45:36 +0000444 std::string CovFilename = Filename.str() + ".gcov";
Yuchen Wu26326ad2013-12-03 00:57:11 +0000445 std::string ErrorInfo;
446 raw_fd_ostream OS(CovFilename.c_str(), ErrorInfo);
447 if (!ErrorInfo.empty())
448 errs() << ErrorInfo << "\n";
449
Yuchen Wu8aac4f62013-11-19 20:57:20 +0000450 OS << " -: 0:Source:" << Filename << "\n";
Yuchen Wu21517e42013-12-04 05:07:36 +0000451 OS << " -: 0:Graph:" << GCNOFile << "\n";
452 OS << " -: 0:Data:" << GCDAFile << "\n";
Yuchen Wu8aac4f62013-11-19 20:57:20 +0000453 OS << " -: 0:Runs:" << RunCount << "\n";
454 OS << " -: 0:Programs:" << ProgramCount << "\n";
455
Yuchen Wu1c068162013-12-03 01:35:31 +0000456 const LineData &Line = I->second;
Yuchen Wu342714c2013-12-13 01:15:07 +0000457 for (uint32_t LineIndex = 0; !AllLines.empty(); ++LineIndex) {
Yuchen Wu73dc3812013-12-18 18:40:15 +0000458 if (Options.BranchInfo) {
Yuchen Wu342714c2013-12-13 01:15:07 +0000459 FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
460 if (FuncsIt != Line.Functions.end())
461 printFunctionSummary(OS, FuncsIt->second);
462 }
Yuchen Wu1c068162013-12-03 01:35:31 +0000463
Yuchen Wu342714c2013-12-13 01:15:07 +0000464 BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
465 if (BlocksIt == Line.Blocks.end()) {
466 // No basic blocks are on this line. Not an executable line of code.
467 OS << " -:";
468 std::pair<StringRef, StringRef> P = AllLines.split('\n');
469 OS << format("%5u:", LineIndex+1) << P.first << "\n";
470 AllLines = P.second;
471 } else {
Yuchen Wu8f1c8812013-12-03 00:38:21 +0000472 const BlockVector &Blocks = BlocksIt->second;
Yuchen Wu342714c2013-12-13 01:15:07 +0000473
474 // Add up the block counts to form line counts.
Yuchen Wu8f1c8812013-12-03 00:38:21 +0000475 uint64_t LineCount = 0;
476 for (BlockVector::const_iterator I = Blocks.begin(), E = Blocks.end();
477 I != E; ++I) {
Yuchen Wu8c6bb5f2013-12-10 01:02:07 +0000478 const GCOVBlock *Block = *I;
479 if (Options.AllBlocks) {
480 // Only take the highest block count for that line.
481 uint64_t BlockCount = Block->getCount();
482 LineCount = LineCount > BlockCount ? LineCount : BlockCount;
483 } else {
484 // Sum up all of the block counts.
485 LineCount += Block->getCount();
486 }
Yuchen Wu8f1c8812013-12-03 00:38:21 +0000487 }
488 if (LineCount == 0)
Yuchen Wudbcf1972013-11-02 00:09:17 +0000489 OS << " #####:";
Yuchen Wu48342ee2013-10-23 19:45:03 +0000490 else
Yuchen Wu8f1c8812013-12-03 00:38:21 +0000491 OS << format("%9" PRIu64 ":", LineCount);
Yuchen Wu8c6bb5f2013-12-10 01:02:07 +0000492
Yuchen Wu342714c2013-12-13 01:15:07 +0000493 std::pair<StringRef, StringRef> P = AllLines.split('\n');
494 OS << format("%5u:", LineIndex+1) << P.first << "\n";
495 AllLines = P.second;
496
Yuchen Wu8c6bb5f2013-12-10 01:02:07 +0000497 uint32_t BlockNo = 0;
Yuchen Wu342714c2013-12-13 01:15:07 +0000498 uint32_t EdgeNo = 0;
Yuchen Wu8c6bb5f2013-12-10 01:02:07 +0000499 for (BlockVector::const_iterator I = Blocks.begin(), E = Blocks.end();
500 I != E; ++I) {
501 const GCOVBlock *Block = *I;
Yuchen Wu8c6bb5f2013-12-10 01:02:07 +0000502
Yuchen Wu342714c2013-12-13 01:15:07 +0000503 // Only print block and branch information at the end of the block.
504 if (Block->getLastLine() != LineIndex+1)
505 continue;
506 if (Options.AllBlocks)
507 printBlockInfo(OS, *Block, LineIndex, BlockNo);
Yuchen Wu73dc3812013-12-18 18:40:15 +0000508 if (Options.BranchInfo) {
Yuchen Wu66d93b82013-12-16 22:14:02 +0000509 size_t NumEdges = Block->getNumDstEdges();
510 if (NumEdges > 1)
511 printBranchInfo(OS, *Block, EdgeNo);
512 else if (Options.UncondBranch && NumEdges == 1)
513 printUncondBranchInfo(OS, EdgeNo, (*Block->dst_begin())->Count);
514 }
Yuchen Wu8c6bb5f2013-12-10 01:02:07 +0000515 }
516 }
Devang Patel37140652011-09-28 18:50:00 +0000517 }
518 }
519}
Yuchen Wu342714c2013-12-13 01:15:07 +0000520
521/// printFunctionSummary - Print function and block summary.
522void FileInfo::printFunctionSummary(raw_fd_ostream &OS,
523 const FunctionVector &Funcs) const {
524 for (FunctionVector::const_iterator I = Funcs.begin(), E = Funcs.end();
525 I != E; ++I) {
526 const GCOVFunction *Func = *I;
527 uint64_t EntryCount = Func->getEntryCount();
Yuchen Wuc9b2dcd2013-12-18 18:46:25 +0000528 uint32_t BlocksExec = 0;
Yuchen Wu342714c2013-12-13 01:15:07 +0000529 for (GCOVFunction::BlockIterator I = Func->block_begin(),
530 E = Func->block_end(); I != E; ++I) {
531 const GCOVBlock *Block = *I;
532 if (Block->getNumDstEdges() && Block->getCount())
Yuchen Wuc9b2dcd2013-12-18 18:46:25 +0000533 ++BlocksExec;
Yuchen Wu342714c2013-12-13 01:15:07 +0000534 }
535
536 OS << "function " << Func->getName() << " called " << EntryCount
537 << " returned " << safeDiv(Func->getExitCount()*100, EntryCount)
538 << "% blocks executed "
Yuchen Wuc9b2dcd2013-12-18 18:46:25 +0000539 << safeDiv(BlocksExec*100, Func->getNumBlocks()-1) << "%\n";
Yuchen Wu342714c2013-12-13 01:15:07 +0000540 }
541}
542
543/// printBlockInfo - Output counts for each block.
544void FileInfo::printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
545 uint32_t LineIndex, uint32_t &BlockNo) const {
546 if (Block.getCount() == 0)
547 OS << " $$$$$:";
548 else
549 OS << format("%9" PRIu64 ":", Block.getCount());
550 OS << format("%5u-block %2u\n", LineIndex+1, BlockNo++);
551}
552
Yuchen Wu66d93b82013-12-16 22:14:02 +0000553/// printBranchInfo - Print conditional branch probabilities.
Yuchen Wu342714c2013-12-13 01:15:07 +0000554void FileInfo::printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
Yuchen Wu66d93b82013-12-16 22:14:02 +0000555 uint32_t &EdgeNo) const {
Yuchen Wu342714c2013-12-13 01:15:07 +0000556 SmallVector<uint64_t, 16> BranchCounts;
557 uint64_t TotalCounts = 0;
558 for (GCOVBlock::EdgeIterator I = Block.dst_begin(), E = Block.dst_end();
559 I != E; ++I) {
560 const GCOVEdge *Edge = *I;
561 BranchCounts.push_back(Edge->Count);
562 TotalCounts += Edge->Count;
563 }
564
565 for (SmallVectorImpl<uint64_t>::const_iterator I = BranchCounts.begin(),
566 E = BranchCounts.end(); I != E; ++I) {
Yuchen Wu73dc3812013-12-18 18:40:15 +0000567 OS << format("branch %2u ", EdgeNo++)
568 << formatBranchInfo(Options, *I, TotalCounts) << "\n";
Yuchen Wu342714c2013-12-13 01:15:07 +0000569 }
570}
Yuchen Wu66d93b82013-12-16 22:14:02 +0000571
572/// printUncondBranchInfo - Print unconditional branch probabilities.
573void FileInfo::printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo,
574 uint64_t Count) const {
Yuchen Wu73dc3812013-12-18 18:40:15 +0000575 OS << format("unconditional %2u ", EdgeNo++)
576 << formatBranchInfo(Options, Count, Count) << "\n";
Yuchen Wu66d93b82013-12-16 22:14:02 +0000577}