blob: a33da2a55251d48c08520f6c77738a5c2b0c2b25 [file] [log] [blame]
Devang Patel58c62002011-10-04 17:24:48 +00001//===- GCOVr.cpp - LLVM coverage tool -------------------------------------===//
Devang Pateld02c42b2011-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//
Devang Patel58c62002011-10-04 17:24:48 +000010// GCOV implements the interface to read and write coverage files that use
11// 'gcov' format.
Devang Pateld02c42b2011-09-28 18:50:00 +000012//
Devang Pateld02c42b2011-09-28 18:50:00 +000013//===----------------------------------------------------------------------===//
14
Yuchen Wu81e38282013-10-25 02:22:24 +000015#include "llvm/Support/Debug.h"
Devang Patel58c62002011-10-04 17:24:48 +000016#include "llvm/Support/GCOV.h"
Devang Pateld02c42b2011-09-28 18:50:00 +000017#include "llvm/ADT/OwningPtr.h"
Devang Patel7a502022011-09-29 16:46:47 +000018#include "llvm/ADT/STLExtras.h"
Bob Wilsone877eeb2013-10-22 05:09:41 +000019#include "llvm/Support/Format.h"
Devang Pateld02c42b2011-09-28 18:50:00 +000020#include "llvm/Support/MemoryObject.h"
21#include "llvm/Support/system_error.h"
22using namespace llvm;
23
24//===----------------------------------------------------------------------===//
25// GCOVFile implementation.
26
27/// ~GCOVFile - Delete GCOVFile and its content.
28GCOVFile::~GCOVFile() {
29 DeleteContainerPointers(Functions);
30}
31
Devang Patel0066f922011-09-29 17:06:40 +000032/// isGCDAFile - Return true if Format identifies a .gcda file.
Bill Wendlinge4fb6ea2012-08-31 17:31:28 +000033static bool isGCDAFile(GCOV::GCOVFormat Format) {
34 return Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404;
Devang Patel0066f922011-09-29 17:06:40 +000035}
36
37/// isGCNOFile - Return true if Format identifies a .gcno file.
Bill Wendlinge4fb6ea2012-08-31 17:31:28 +000038static bool isGCNOFile(GCOV::GCOVFormat Format) {
39 return Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404;
Devang Patel0066f922011-09-29 17:06:40 +000040}
41
Devang Pateld02c42b2011-09-28 18:50:00 +000042/// read - Read GCOV buffer.
43bool GCOVFile::read(GCOVBuffer &Buffer) {
Bill Wendlinge4fb6ea2012-08-31 17:31:28 +000044 GCOV::GCOVFormat Format = Buffer.readGCOVFormat();
45 if (Format == GCOV::InvalidGCOV)
Devang Pateld02c42b2011-09-28 18:50:00 +000046 return false;
47
Yuchen Wu76fa4d62013-10-25 02:22:21 +000048 if (isGCNOFile(Format)) {
49 while (true) {
50 GCOVFunction *GFun = new GCOVFunction();
51 if (!GFun->read(Buffer, Format))
52 break;
Devang Patel0066f922011-09-29 17:06:40 +000053 Functions.push_back(GFun);
Devang Pateld02c42b2011-09-28 18:50:00 +000054 }
Devang Pateld02c42b2011-09-28 18:50:00 +000055 }
Yuchen Wu76fa4d62013-10-25 02:22:21 +000056 else if (isGCDAFile(Format)) {
57 for (size_t i = 0, e = Functions.size(); i < e; ++i) {
58 bool ReadGCDA = Functions[i]->read(Buffer, Format);
59 (void)ReadGCDA;
60 assert(ReadGCDA && ".gcda data does not match .gcno data");
61 }
Yuchen Wue85959c2013-11-05 01:11:58 +000062 if (Buffer.readObjectTag()) {
63 uint32_t Length = Buffer.readInt();
64 Buffer.readInt(); // checksum
65 Buffer.readInt(); // num
66 RunCount = Buffer.readInt();
67 Buffer.advanceCursor(Length-3);
68 }
69 while (Buffer.readProgramTag()) {
70 uint32_t Length = Buffer.readInt();
71 Buffer.advanceCursor(Length);
Yuchen Wu76fa4d62013-10-25 02:22:21 +000072 ++ProgramCount;
Yuchen Wue85959c2013-11-05 01:11:58 +000073 }
Yuchen Wu76fa4d62013-10-25 02:22:21 +000074 }
75
Devang Pateld02c42b2011-09-28 18:50:00 +000076 return true;
77}
78
Yuchen Wu81e38282013-10-25 02:22:24 +000079/// dump - Dump GCOVFile content to dbgs() for debugging purposes.
Devang Pateld02c42b2011-09-28 18:50:00 +000080void GCOVFile::dump() {
Craig Topper6227d5c2013-07-04 01:31:24 +000081 for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +000082 E = Functions.end(); I != E; ++I)
Devang Pateld02c42b2011-09-28 18:50:00 +000083 (*I)->dump();
84}
85
86/// collectLineCounts - Collect line counts. This must be used after
87/// reading .gcno and .gcda files.
88void GCOVFile::collectLineCounts(FileInfo &FI) {
Craig Topper6227d5c2013-07-04 01:31:24 +000089 for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +000090 E = Functions.end(); I != E; ++I)
Devang Pateld02c42b2011-09-28 18:50:00 +000091 (*I)->collectLineCounts(FI);
Yuchen Wue85959c2013-11-05 01:11:58 +000092 FI.setRunCount(RunCount);
Yuchen Wu76fa4d62013-10-25 02:22:21 +000093 FI.setProgramCount(ProgramCount);
Devang Pateld02c42b2011-09-28 18:50:00 +000094}
95
96//===----------------------------------------------------------------------===//
97// GCOVFunction implementation.
98
99/// ~GCOVFunction - Delete GCOVFunction and its content.
100GCOVFunction::~GCOVFunction() {
101 DeleteContainerPointers(Blocks);
102}
103
Bob Wilson0a2463c2013-10-22 19:54:32 +0000104/// read - Read a function from the buffer. Return false if buffer cursor
Devang Pateld02c42b2011-09-28 18:50:00 +0000105/// does not point to a function tag.
Bill Wendlinge4fb6ea2012-08-31 17:31:28 +0000106bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000107 if (!Buff.readFunctionTag())
108 return false;
109
110 Buff.readInt(); // Function header length
111 Ident = Buff.readInt();
112 Buff.readInt(); // Checksum #1
Bill Wendlinga37d96a2013-06-25 18:13:52 +0000113 if (Format != GCOV::GCNO_402 && Format != GCOV::GCDA_402)
Devang Pateld02c42b2011-09-28 18:50:00 +0000114 Buff.readInt(); // Checksum #2
115
116 Name = Buff.readString();
Bill Wendlinge4fb6ea2012-08-31 17:31:28 +0000117 if (Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404)
Devang Pateld02c42b2011-09-28 18:50:00 +0000118 Filename = Buff.readString();
119
Bill Wendlinge4fb6ea2012-08-31 17:31:28 +0000120 if (Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000121 Buff.readArcTag();
Yuchen Wucbbd2082013-10-24 01:51:04 +0000122 uint32_t i = 0;
Devang Pateld02c42b2011-09-28 18:50:00 +0000123 uint32_t Count = Buff.readInt() / 2;
Yuchen Wucbbd2082013-10-24 01:51:04 +0000124
125 // This for loop adds the counts for each block. A second nested loop is
126 // required to combine the edge counts that are contained in the GCDA file.
127 for (uint32_t Line = 0; i < Count; ++Line) {
128 GCOVBlock &Block = *Blocks[Line];
129 for (size_t Edge = 0, End = Block.getNumEdges(); Edge < End; ++Edge) {
130 assert(i < Count && "Unexpected number of Edges!");
131 Block.addCount(Buff.readInt64());
132 ++i;
133 }
Devang Pateld02c42b2011-09-28 18:50:00 +0000134 }
Chad Rosier90f20042012-02-22 17:25:00 +0000135 return true;
Devang Pateld02c42b2011-09-28 18:50:00 +0000136 }
137
138 LineNumber = Buff.readInt();
139
140 // read blocks.
Nick Lewycky85aa4f62012-09-23 03:58:21 +0000141 bool BlockTagFound = Buff.readBlockTag();
142 (void)BlockTagFound;
143 assert(BlockTagFound && "Block Tag not found!");
Devang Pateld02c42b2011-09-28 18:50:00 +0000144 uint32_t BlockCount = Buff.readInt();
Bob Wilson67fa5392013-10-22 20:02:36 +0000145 for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000146 Buff.readInt(); // Block flags;
147 Blocks.push_back(new GCOVBlock(i));
148 }
149
150 // read edges.
151 while (Buff.readEdgeTag()) {
152 uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
153 uint32_t BlockNo = Buff.readInt();
Nick Lewycky85aa4f62012-09-23 03:58:21 +0000154 assert(BlockNo < BlockCount && "Unexpected Block number!");
Bob Wilson67fa5392013-10-22 20:02:36 +0000155 for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000156 Blocks[BlockNo]->addEdge(Buff.readInt());
157 Buff.readInt(); // Edge flag
158 }
159 }
160
161 // read line table.
162 while (Buff.readLineTag()) {
163 uint32_t LineTableLength = Buff.readInt();
Bob Wilson0a2463c2013-10-22 19:54:32 +0000164 uint32_t EndPos = Buff.getCursor() + LineTableLength*4;
Devang Pateld02c42b2011-09-28 18:50:00 +0000165 uint32_t BlockNo = Buff.readInt();
Nick Lewycky85aa4f62012-09-23 03:58:21 +0000166 assert(BlockNo < BlockCount && "Unexpected Block number!");
Devang Pateld02c42b2011-09-28 18:50:00 +0000167 GCOVBlock *Block = Blocks[BlockNo];
168 Buff.readInt(); // flag
Bob Wilson0a2463c2013-10-22 19:54:32 +0000169 while (Buff.getCursor() != (EndPos - 4)) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000170 StringRef Filename = Buff.readString();
Bob Wilson0a2463c2013-10-22 19:54:32 +0000171 if (Buff.getCursor() == (EndPos - 4)) break;
Devang Pateld02c42b2011-09-28 18:50:00 +0000172 while (uint32_t L = Buff.readInt())
Bill Wendling56cb2292012-07-19 00:11:40 +0000173 Block->addLine(Filename, L);
Devang Pateld02c42b2011-09-28 18:50:00 +0000174 }
175 Buff.readInt(); // flag
176 }
177 return true;
178}
179
Yuchen Wu81e38282013-10-25 02:22:24 +0000180/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
Devang Pateld02c42b2011-09-28 18:50:00 +0000181void GCOVFunction::dump() {
Yuchen Wu81e38282013-10-25 02:22:24 +0000182 dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
Craig Topper6227d5c2013-07-04 01:31:24 +0000183 for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +0000184 E = Blocks.end(); I != E; ++I)
Devang Pateld02c42b2011-09-28 18:50:00 +0000185 (*I)->dump();
186}
187
188/// collectLineCounts - Collect line counts. This must be used after
189/// reading .gcno and .gcda files.
190void GCOVFunction::collectLineCounts(FileInfo &FI) {
Craig Topper6227d5c2013-07-04 01:31:24 +0000191 for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +0000192 E = Blocks.end(); I != E; ++I)
Devang Pateld02c42b2011-09-28 18:50:00 +0000193 (*I)->collectLineCounts(FI);
194}
195
196//===----------------------------------------------------------------------===//
197// GCOVBlock implementation.
198
199/// ~GCOVBlock - Delete GCOVBlock and its content.
200GCOVBlock::~GCOVBlock() {
201 Edges.clear();
202 DeleteContainerSeconds(Lines);
203}
204
205void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) {
206 GCOVLines *&LinesForFile = Lines[Filename];
207 if (!LinesForFile)
208 LinesForFile = new GCOVLines();
209 LinesForFile->add(LineNo);
210}
211
212/// collectLineCounts - Collect line counts. This must be used after
213/// reading .gcno and .gcda files.
214void GCOVBlock::collectLineCounts(FileInfo &FI) {
215 for (StringMap<GCOVLines *>::iterator I = Lines.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +0000216 E = Lines.end(); I != E; ++I)
Devang Pateld02c42b2011-09-28 18:50:00 +0000217 I->second->collectLineCounts(FI, I->first(), Counter);
218}
219
Yuchen Wu81e38282013-10-25 02:22:24 +0000220/// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
Devang Pateld02c42b2011-09-28 18:50:00 +0000221void GCOVBlock::dump() {
Yuchen Wu81e38282013-10-25 02:22:24 +0000222 dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
Devang Pateld02c42b2011-09-28 18:50:00 +0000223 if (!Edges.empty()) {
Yuchen Wu81e38282013-10-25 02:22:24 +0000224 dbgs() << "\tEdges : ";
Craig Topper6227d5c2013-07-04 01:31:24 +0000225 for (SmallVectorImpl<uint32_t>::iterator I = Edges.begin(), E = Edges.end();
Bill Wendling56cb2292012-07-19 00:11:40 +0000226 I != E; ++I)
Yuchen Wu81e38282013-10-25 02:22:24 +0000227 dbgs() << (*I) << ",";
228 dbgs() << "\n";
Devang Pateld02c42b2011-09-28 18:50:00 +0000229 }
230 if (!Lines.empty()) {
Yuchen Wu81e38282013-10-25 02:22:24 +0000231 dbgs() << "\tLines : ";
Devang Pateld02c42b2011-09-28 18:50:00 +0000232 for (StringMap<GCOVLines *>::iterator LI = Lines.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +0000233 LE = Lines.end(); LI != LE; ++LI) {
Yuchen Wu81e38282013-10-25 02:22:24 +0000234 dbgs() << LI->first() << " -> ";
Devang Pateld02c42b2011-09-28 18:50:00 +0000235 LI->second->dump();
Yuchen Wu81e38282013-10-25 02:22:24 +0000236 dbgs() << "\n";
Devang Pateld02c42b2011-09-28 18:50:00 +0000237 }
238 }
239}
240
241//===----------------------------------------------------------------------===//
242// GCOVLines implementation.
243
244/// collectLineCounts - Collect line counts. This must be used after
245/// reading .gcno and .gcda files.
246void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename,
Bob Wilson51ec77d2013-10-22 17:43:47 +0000247 uint64_t Count) {
Craig Topper6227d5c2013-07-04 01:31:24 +0000248 for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +0000249 E = Lines.end(); I != E; ++I)
Devang Pateld02c42b2011-09-28 18:50:00 +0000250 FI.addLineCount(Filename, *I, Count);
251}
252
Yuchen Wu81e38282013-10-25 02:22:24 +0000253/// dump - Dump GCOVLines content to dbgs() for debugging purposes.
Devang Pateld02c42b2011-09-28 18:50:00 +0000254void GCOVLines::dump() {
Craig Topper6227d5c2013-07-04 01:31:24 +0000255 for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
Bill Wendling56cb2292012-07-19 00:11:40 +0000256 E = Lines.end(); I != E; ++I)
Yuchen Wu81e38282013-10-25 02:22:24 +0000257 dbgs() << (*I) << ",";
Devang Pateld02c42b2011-09-28 18:50:00 +0000258}
259
260//===----------------------------------------------------------------------===//
261// FileInfo implementation.
262
Devang Pateld02c42b2011-09-28 18:50:00 +0000263/// print - Print source files with collected line count information.
Yuchen Wudaaa8b72013-11-02 00:09:17 +0000264void FileInfo::print(raw_fd_ostream &OS, StringRef gcnoFile,
265 StringRef gcdaFile) {
Devang Pateld02c42b2011-09-28 18:50:00 +0000266 for (StringMap<LineCounts>::iterator I = LineInfo.begin(), E = LineInfo.end();
267 I != E; ++I) {
268 StringRef Filename = I->first();
Yuchen Wuf44533c2013-11-05 01:56:29 +0000269 OS << " -: 0:Source:" << Filename << "\n";
270 OS << " -: 0:Graph:" << gcnoFile << "\n";
271 OS << " -: 0:Data:" << gcdaFile << "\n";
272 OS << " -: 0:Runs:" << RunCount << "\n";
273 OS << " -: 0:Programs:" << ProgramCount << "\n";
274 LineCounts &L = LineInfo[Filename];
Devang Pateld02c42b2011-09-28 18:50:00 +0000275 OwningPtr<MemoryBuffer> Buff;
276 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
277 errs() << Filename << ": " << ec.message() << "\n";
278 return;
279 }
280 StringRef AllLines = Buff.take()->getBuffer();
Yuchen Wu9db96632013-10-23 19:45:03 +0000281 uint32_t i = 0;
282 while (!AllLines.empty()) {
283 if (L.find(i) != L.end()) {
284 if (L[i] == 0)
Yuchen Wudaaa8b72013-11-02 00:09:17 +0000285 OS << " #####:";
Yuchen Wu9db96632013-10-23 19:45:03 +0000286 else
Yuchen Wudaaa8b72013-11-02 00:09:17 +0000287 OS << format("%9lu:", L[i]);
Yuchen Wu9db96632013-10-23 19:45:03 +0000288 } else {
Yuchen Wudaaa8b72013-11-02 00:09:17 +0000289 OS << " -:";
Yuchen Wu9db96632013-10-23 19:45:03 +0000290 }
Devang Pateld02c42b2011-09-28 18:50:00 +0000291 std::pair<StringRef, StringRef> P = AllLines.split('\n');
292 if (AllLines != P.first)
Yuchen Wudaaa8b72013-11-02 00:09:17 +0000293 OS << format("%5u:", i+1) << P.first;
294 OS << "\n";
Devang Pateld02c42b2011-09-28 18:50:00 +0000295 AllLines = P.second;
Yuchen Wu9db96632013-10-23 19:45:03 +0000296 ++i;
Devang Pateld02c42b2011-09-28 18:50:00 +0000297 }
298 }
299}
300