Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/ProfileData/GCOV.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- GCOV.cpp - LLVM coverage tool --------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// GCOV implements the interface to read and write coverage files that use
10
// 'gcov' format.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/ProfileData/GCOV.h"
15
#include "llvm/ADT/STLExtras.h"
16
#include "llvm/Config/llvm-config.h"
17
#include "llvm/Support/Debug.h"
18
#include "llvm/Support/FileSystem.h"
19
#include "llvm/Support/Format.h"
20
#include "llvm/Support/Path.h"
21
#include "llvm/Support/MD5.h"
22
#include "llvm/Support/raw_ostream.h"
23
#include <algorithm>
24
#include <system_error>
25
26
using namespace llvm;
27
28
//===----------------------------------------------------------------------===//
29
// GCOVFile implementation.
30
31
/// readGCNO - Read GCNO buffer.
32
31
bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
33
31
  if (!Buffer.readGCNOFormat())
34
0
    return false;
35
31
  if (!Buffer.readGCOVVersion(Version))
36
0
    return false;
37
31
38
31
  if (!Buffer.readInt(Checksum))
39
0
    return false;
40
248
  
while (31
true) {
41
248
    if (!Buffer.readFunctionTag())
42
30
      break;
43
218
    auto GFun = make_unique<GCOVFunction>(*this);
44
218
    if (!GFun->readGCNO(Buffer, Version))
45
1
      return false;
46
217
    Functions.push_back(std::move(GFun));
47
217
  }
48
31
49
31
  GCNOInitialized = true;
50
30
  return true;
51
31
}
52
53
/// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
54
/// called after readGCNO().
55
23
bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
56
23
  assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
57
23
  if (!Buffer.readGCDAFormat())
58
0
    return false;
59
23
  GCOV::GCOVVersion GCDAVersion;
60
23
  if (!Buffer.readGCOVVersion(GCDAVersion))
61
0
    return false;
62
23
  if (Version != GCDAVersion) {
63
0
    errs() << "GCOV versions do not match.\n";
64
0
    return false;
65
0
  }
66
23
67
23
  uint32_t GCDAChecksum;
68
23
  if (!Buffer.readInt(GCDAChecksum))
69
0
    return false;
70
23
  if (Checksum != GCDAChecksum) {
71
2
    errs() << "File checksums do not match: " << Checksum
72
2
           << " != " << GCDAChecksum << ".\n";
73
2
    return false;
74
2
  }
75
200
  
for (size_t i = 0, e = Functions.size(); 21
i < e;
++i179
) {
76
179
    if (!Buffer.readFunctionTag()) {
77
0
      errs() << "Unexpected number of functions.\n";
78
0
      return false;
79
0
    }
80
179
    if (!Functions[i]->readGCDA(Buffer, Version))
81
0
      return false;
82
179
  }
83
21
  if (Buffer.readObjectTag()) {
84
21
    uint32_t Length;
85
21
    uint32_t Dummy;
86
21
    if (!Buffer.readInt(Length))
87
0
      return false;
88
21
    if (!Buffer.readInt(Dummy))
89
0
      return false; // checksum
90
21
    if (!Buffer.readInt(Dummy))
91
0
      return false; // num
92
21
    if (!Buffer.readInt(RunCount))
93
0
      return false;
94
21
    Buffer.advanceCursor(Length - 3);
95
21
  }
96
42
  
while (21
Buffer.readProgramTag()) {
97
21
    uint32_t Length;
98
21
    if (!Buffer.readInt(Length))
99
0
      return false;
100
21
    Buffer.advanceCursor(Length);
101
21
    ++ProgramCount;
102
21
  }
103
21
104
21
  return true;
105
21
}
106
107
6
void GCOVFile::print(raw_ostream &OS) const {
108
6
  for (const auto &FPtr : Functions)
109
8
    FPtr->print(OS);
110
6
}
111
112
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
113
/// dump - Dump GCOVFile content to dbgs() for debugging purposes.
114
LLVM_DUMP_METHOD void GCOVFile::dump() const { print(dbgs()); }
115
#endif
116
117
/// collectLineCounts - Collect line counts. This must be used after
118
/// reading .gcno and .gcda files.
119
28
void GCOVFile::collectLineCounts(FileInfo &FI) {
120
28
  for (const auto &FPtr : Functions)
121
197
    FPtr->collectLineCounts(FI);
122
28
  FI.setRunCount(RunCount);
123
28
  FI.setProgramCount(ProgramCount);
124
28
}
125
126
//===----------------------------------------------------------------------===//
127
// GCOVFunction implementation.
128
129
/// readGCNO - Read a function from the GCNO buffer. Return false if an error
130
/// occurs.
131
218
bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
132
218
  uint32_t Dummy;
133
218
  if (!Buff.readInt(Dummy))
134
0
    return false; // Function header length
135
218
  if (!Buff.readInt(Ident))
136
0
    return false;
137
218
  if (!Buff.readInt(Checksum))
138
0
    return false;
139
218
  if (Version != GCOV::V402) {
140
1
    uint32_t CfgChecksum;
141
1
    if (!Buff.readInt(CfgChecksum))
142
0
      return false;
143
1
    if (Parent.getChecksum() != CfgChecksum) {
144
0
      errs() << "File checksums do not match: " << Parent.getChecksum()
145
0
             << " != " << CfgChecksum << " in (" << Name << ").\n";
146
0
      return false;
147
0
    }
148
218
  }
149
218
  if (!Buff.readString(Name))
150
0
    return false;
151
218
  if (!Buff.readString(Filename))
152
0
    return false;
153
218
  if (!Buff.readInt(LineNumber))
154
0
    return false;
155
218
156
218
  // read blocks.
157
218
  if (!Buff.readBlockTag()) {
158
0
    errs() << "Block tag not found.\n";
159
0
    return false;
160
0
  }
161
218
  uint32_t BlockCount;
162
218
  if (!Buff.readInt(BlockCount))
163
1
    return false;
164
1.36k
  
for (uint32_t i = 0, e = BlockCount; 217
i != e;
++i1.14k
) {
165
1.14k
    if (!Buff.readInt(Dummy))
166
0
      return false; // Block flags;
167
1.14k
    Blocks.push_back(make_unique<GCOVBlock>(*this, i));
168
1.14k
  }
169
217
170
217
  // read edges.
171
1.14k
  
while (217
Buff.readEdgeTag()) {
172
926
    uint32_t EdgeCount;
173
926
    if (!Buff.readInt(EdgeCount))
174
0
      return false;
175
926
    EdgeCount = (EdgeCount - 1) / 2;
176
926
    uint32_t BlockNo;
177
926
    if (!Buff.readInt(BlockNo))
178
0
      return false;
179
926
    if (BlockNo >= BlockCount) {
180
0
      errs() << "Unexpected block number: " << BlockNo << " (in " << Name
181
0
             << ").\n";
182
0
      return false;
183
0
    }
184
2.03k
    
for (uint32_t i = 0, e = EdgeCount; 926
i != e;
++i1.11k
) {
185
1.11k
      uint32_t Dst;
186
1.11k
      if (!Buff.readInt(Dst))
187
0
        return false;
188
1.11k
      Edges.push_back(make_unique<GCOVEdge>(*Blocks[BlockNo], *Blocks[Dst]));
189
1.11k
      GCOVEdge *Edge = Edges.back().get();
190
1.11k
      Blocks[BlockNo]->addDstEdge(Edge);
191
1.11k
      Blocks[Dst]->addSrcEdge(Edge);
192
1.11k
      if (!Buff.readInt(Dummy))
193
0
        return false; // Edge flag
194
1.11k
    }
195
926
  }
196
217
197
217
  // read line table.
198
1.14k
  
while (217
Buff.readLineTag()) {
199
926
    uint32_t LineTableLength;
200
926
    // Read the length of this line table.
201
926
    if (!Buff.readInt(LineTableLength))
202
0
      return false;
203
926
    uint32_t EndPos = Buff.getCursor() + LineTableLength * 4;
204
926
    uint32_t BlockNo;
205
926
    // Read the block number this table is associated with.
206
926
    if (!Buff.readInt(BlockNo))
207
0
      return false;
208
926
    if (BlockNo >= BlockCount) {
209
0
      errs() << "Unexpected block number: " << BlockNo << " (in " << Name
210
0
             << ").\n";
211
0
      return false;
212
0
    }
213
926
    GCOVBlock &Block = *Blocks[BlockNo];
214
926
    // Read the word that pads the beginning of the line table. This may be a
215
926
    // flag of some sort, but seems to always be zero.
216
926
    if (!Buff.readInt(Dummy))
217
0
      return false;
218
926
219
926
    // Line information starts here and continues up until the last word.
220
926
    if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) {
221
721
      StringRef F;
222
721
      // Read the source file name.
223
721
      if (!Buff.readString(F))
224
0
        return false;
225
721
      if (Filename != F) {
226
0
        errs() << "Multiple sources for a single basic block: " << Filename
227
0
               << " != " << F << " (in " << Name << ").\n";
228
0
        return false;
229
0
      }
230
721
      // Read lines up to, but not including, the null terminator.
231
1.76k
      
while (721
Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
232
1.03k
        uint32_t Line;
233
1.03k
        if (!Buff.readInt(Line))
234
0
          return false;
235
1.03k
        // Line 0 means this instruction was injected by the compiler. Skip it.
236
1.03k
        if (!Line)
237
3
          continue;
238
1.03k
        Block.addLine(Line);
239
1.03k
      }
240
721
      // Read the null terminator.
241
721
      if (!Buff.readInt(Dummy))
242
0
        return false;
243
926
    }
244
926
    // The last word is either a flag or padding, it isn't clear which. Skip
245
926
    // over it.
246
926
    if (!Buff.readInt(Dummy))
247
0
      return false;
248
926
  }
249
217
  return true;
250
217
}
251
252
/// readGCDA - Read a function from the GCDA buffer. Return false if an error
253
/// occurs.
254
179
bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
255
179
  uint32_t HeaderLength;
256
179
  if (!Buff.readInt(HeaderLength))
257
0
    return false; // Function header length
258
179
259
179
  uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t);
260
179
261
179
  uint32_t GCDAIdent;
262
179
  if (!Buff.readInt(GCDAIdent))
263
0
    return false;
264
179
  if (Ident != GCDAIdent) {
265
0
    errs() << "Function identifiers do not match: " << Ident
266
0
           << " != " << GCDAIdent << " (in " << Name << ").\n";
267
0
    return false;
268
0
  }
269
179
270
179
  uint32_t GCDAChecksum;
271
179
  if (!Buff.readInt(GCDAChecksum))
272
0
    return false;
273
179
  if (Checksum != GCDAChecksum) {
274
0
    errs() << "Function checksums do not match: " << Checksum
275
0
           << " != " << GCDAChecksum << " (in " << Name << ").\n";
276
0
    return false;
277
0
  }
278
179
279
179
  uint32_t CfgChecksum;
280
179
  if (Version != GCOV::V402) {
281
1
    if (!Buff.readInt(CfgChecksum))
282
0
      return false;
283
1
    if (Parent.getChecksum() != CfgChecksum) {
284
0
      errs() << "File checksums do not match: " << Parent.getChecksum()
285
0
             << " != " << CfgChecksum << " (in " << Name << ").\n";
286
0
      return false;
287
0
    }
288
179
  }
289
179
290
179
  if (Buff.getCursor() < EndPos) {
291
178
    StringRef GCDAName;
292
178
    if (!Buff.readString(GCDAName))
293
0
      return false;
294
178
    if (Name != GCDAName) {
295
0
      errs() << "Function names do not match: " << Name << " != " << GCDAName
296
0
             << ".\n";
297
0
      return false;
298
0
    }
299
179
  }
300
179
301
179
  if (!Buff.readArcTag()) {
302
0
    errs() << "Arc tag not found (in " << Name << ").\n";
303
0
    return false;
304
0
  }
305
179
306
179
  uint32_t Count;
307
179
  if (!Buff.readInt(Count))
308
0
    return false;
309
179
  Count /= 2;
310
179
311
179
  // This for loop adds the counts for each block. A second nested loop is
312
179
  // required to combine the edge counts that are contained in the GCDA file.
313
950
  for (uint32_t BlockNo = 0; Count > 0; 
++BlockNo771
) {
314
771
    // The last block is always reserved for exit block
315
771
    if (BlockNo >= Blocks.size()) {
316
0
      errs() << "Unexpected number of edges (in " << Name << ").\n";
317
0
      return false;
318
0
    }
319
771
    if (BlockNo == Blocks.size() - 1)
320
1
      errs() << "(" << Name << ") has arcs from exit block.\n";
321
771
    GCOVBlock &Block = *Blocks[BlockNo];
322
1.69k
    for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
323
924
         ++EdgeNo) {
324
924
      if (Count == 0) {
325
0
        errs() << "Unexpected number of edges (in " << Name << ").\n";
326
0
        return false;
327
0
      }
328
924
      uint64_t ArcCount;
329
924
      if (!Buff.readInt64(ArcCount))
330
0
        return false;
331
924
      Block.addCount(EdgeNo, ArcCount);
332
924
      --Count;
333
924
    }
334
771
    Block.sortDstEdges();
335
771
  }
336
179
  return true;
337
179
}
338
339
/// getEntryCount - Get the number of times the function was called by
340
/// retrieving the entry block's count.
341
40
uint64_t GCOVFunction::getEntryCount() const {
342
40
  return Blocks.front()->getCount();
343
40
}
344
345
/// getExitCount - Get the number of times the function returned by retrieving
346
/// the exit block's count.
347
40
uint64_t GCOVFunction::getExitCount() const {
348
40
  return Blocks.back()->getCount();
349
40
}
350
351
8
void GCOVFunction::print(raw_ostream &OS) const {
352
8
  OS << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
353
8
     << LineNumber << "\n";
354
8
  for (const auto &Block : Blocks)
355
32
    Block->print(OS);
356
8
}
357
358
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
359
/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
360
LLVM_DUMP_METHOD void GCOVFunction::dump() const { print(dbgs()); }
361
#endif
362
363
/// collectLineCounts - Collect line counts. This must be used after
364
/// reading .gcno and .gcda files.
365
197
void GCOVFunction::collectLineCounts(FileInfo &FI) {
366
197
  // If the line number is zero, this is a function that doesn't actually appear
367
197
  // in the source file, so there isn't anything we can do with it.
368
197
  if (LineNumber == 0)
369
2
    return;
370
195
371
195
  for (const auto &Block : Blocks)
372
1.02k
    Block->collectLineCounts(FI);
373
195
  FI.addFunctionLine(Filename, LineNumber, this);
374
195
}
375
376
//===----------------------------------------------------------------------===//
377
// GCOVBlock implementation.
378
379
/// ~GCOVBlock - Delete GCOVBlock and its content.
380
1.14k
GCOVBlock::~GCOVBlock() {
381
1.14k
  SrcEdges.clear();
382
1.14k
  DstEdges.clear();
383
1.14k
  Lines.clear();
384
1.14k
}
385
386
/// addCount - Add to block counter while storing the edge count. If the
387
/// destination has no outgoing edges, also update that block's count too.
388
924
void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
389
924
  assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
390
924
  DstEdges[DstEdgeNo]->Count = N;
391
924
  Counter += N;
392
924
  if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges())
393
179
    DstEdges[DstEdgeNo]->Dst.Counter += N;
394
924
}
395
396
/// sortDstEdges - Sort destination edges by block number, nop if already
397
/// sorted. This is required for printing branch info in the correct order.
398
771
void GCOVBlock::sortDstEdges() {
399
771
  if (!DstEdgesAreSorted)
400
119
    
llvm::stable_sort(DstEdges, [](const GCOVEdge *E1, const GCOVEdge *E2) 17
{
401
119
      return E1->Dst.Number < E2->Dst.Number;
402
119
    });
403
771
}
404
405
/// collectLineCounts - Collect line counts. This must be used after
406
/// reading .gcno and .gcda files.
407
1.02k
void GCOVBlock::collectLineCounts(FileInfo &FI) {
408
1.02k
  for (uint32_t N : Lines)
409
938
    FI.addBlockLine(Parent.getFilename(), N, this);
410
1.02k
}
411
412
32
void GCOVBlock::print(raw_ostream &OS) const {
413
32
  OS << "Block : " << Number << " Counter : " << Counter << "\n";
414
32
  if (!SrcEdges.empty()) {
415
24
    OS << "\tSource Edges : ";
416
24
    for (const GCOVEdge *Edge : SrcEdges)
417
28
      OS << Edge->Src.Number << " (" << Edge->Count << "), ";
418
24
    OS << "\n";
419
24
  }
420
32
  if (!DstEdges.empty()) {
421
24
    OS << "\tDestination Edges : ";
422
24
    for (const GCOVEdge *Edge : DstEdges)
423
28
      OS << Edge->Dst.Number << " (" << Edge->Count << "), ";
424
24
    OS << "\n";
425
24
  }
426
32
  if (!Lines.empty()) {
427
24
    OS << "\tLines : ";
428
24
    for (uint32_t N : Lines)
429
32
      OS << (N) << ",";
430
24
    OS << "\n";
431
24
  }
432
32
}
433
434
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
435
/// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
436
LLVM_DUMP_METHOD void GCOVBlock::dump() const { print(dbgs()); }
437
#endif
438
439
//===----------------------------------------------------------------------===//
440
// Cycles detection
441
//
442
// The algorithm in GCC is based on the algorihtm by Hawick & James:
443
//   "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
444
//   http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf.
445
446
/// Get the count for the detected cycle.
447
1
uint64_t GCOVBlock::getCycleCount(const Edges &Path) {
448
1
  uint64_t CycleCount = std::numeric_limits<uint64_t>::max();
449
3
  for (auto E : Path) {
450
3
    CycleCount = std::min(E->CyclesCount, CycleCount);
451
3
  }
452
3
  for (auto E : Path) {
453
3
    E->CyclesCount -= CycleCount;
454
3
  }
455
1
  return CycleCount;
456
1
}
457
458
/// Unblock a vertex previously marked as blocked.
459
void GCOVBlock::unblock(const GCOVBlock *U, BlockVector &Blocked,
460
3
                        BlockVectorLists &BlockLists) {
461
3
  auto it = find(Blocked, U);
462
3
  if (it == Blocked.end()) {
463
0
    return;
464
0
  }
465
3
466
3
  const size_t index = it - Blocked.begin();
467
3
  Blocked.erase(it);
468
3
469
3
  const BlockVector ToUnblock(BlockLists[index]);
470
3
  BlockLists.erase(BlockLists.begin() + index);
471
3
  for (auto GB : ToUnblock) {
472
0
    GCOVBlock::unblock(GB, Blocked, BlockLists);
473
0
  }
474
3
}
475
476
bool GCOVBlock::lookForCircuit(const GCOVBlock *V, const GCOVBlock *Start,
477
                               Edges &Path, BlockVector &Blocked,
478
                               BlockVectorLists &BlockLists,
479
1.04k
                               const BlockVector &Blocks, uint64_t &Count) {
480
1.04k
  Blocked.push_back(V);
481
1.04k
  BlockLists.emplace_back(BlockVector());
482
1.04k
  bool FoundCircuit = false;
483
1.04k
484
1.35k
  for (auto E : V->dsts()) {
485
1.35k
    const GCOVBlock *W = &E->Dst;
486
1.35k
    if (W < Start || 
find(Blocks, W) == Blocks.end()1.27k
) {
487
1.24k
      continue;
488
1.24k
    }
489
108
490
108
    Path.push_back(E);
491
108
492
108
    if (W == Start) {
493
1
      // We've a cycle.
494
1
      Count += GCOVBlock::getCycleCount(Path);
495
1
      FoundCircuit = true;
496
107
    } else if (find(Blocked, W) == Blocked.end() && // W is not blocked.
497
107
               GCOVBlock::lookForCircuit(W, Start, Path, Blocked, BlockLists,
498
104
                                         Blocks, Count)) {
499
2
      FoundCircuit = true;
500
2
    }
501
108
502
108
    Path.pop_back();
503
108
  }
504
1.04k
505
1.04k
  if (FoundCircuit) {
506
3
    GCOVBlock::unblock(V, Blocked, BlockLists);
507
1.03k
  } else {
508
1.34k
    for (auto E : V->dsts()) {
509
1.34k
      const GCOVBlock *W = &E->Dst;
510
1.34k
      if (W < Start || 
find(Blocks, W) == Blocks.end()1.27k
) {
511
1.24k
        continue;
512
1.24k
      }
513
105
      const size_t index = find(Blocked, W) - Blocked.begin();
514
105
      BlockVector &List = BlockLists[index];
515
105
      if (find(List, V) == List.end()) {
516
105
        List.push_back(V);
517
105
      }
518
105
    }
519
1.03k
  }
520
1.04k
521
1.04k
  return FoundCircuit;
522
1.04k
}
523
524
/// Get the count for the list of blocks which lie on the same line.
525
738
void GCOVBlock::getCyclesCount(const BlockVector &Blocks, uint64_t &Count) {
526
938
  for (auto Block : Blocks) {
527
938
    Edges Path;
528
938
    BlockVector Blocked;
529
938
    BlockVectorLists BlockLists;
530
938
531
938
    GCOVBlock::lookForCircuit(Block, Block, Path, Blocked, BlockLists, Blocks,
532
938
                              Count);
533
938
  }
534
738
}
535
536
/// Get the count for the list of blocks which lie on the same line.
537
738
uint64_t GCOVBlock::getLineCount(const BlockVector &Blocks) {
538
738
  uint64_t Count = 0;
539
738
540
938
  for (auto Block : Blocks) {
541
938
    if (Block->getNumSrcEdges() == 0) {
542
18
      // The block has no predecessors and a non-null counter
543
18
      // (can be the case with entry block in functions).
544
18
      Count += Block->getCount();
545
920
    } else {
546
920
      // Add counts from predecessors that are not on the same line.
547
1.10k
      for (auto E : Block->srcs()) {
548
1.10k
        const GCOVBlock *W = &E->Src;
549
1.10k
        if (find(Blocks, W) == Blocks.end()) {
550
943
          Count += E->Count;
551
943
        }
552
1.10k
      }
553
920
    }
554
1.16k
    for (auto E : Block->dsts()) {
555
1.16k
      E->CyclesCount = E->Count;
556
1.16k
    }
557
938
  }
558
738
559
738
  GCOVBlock::getCyclesCount(Blocks, Count);
560
738
561
738
  return Count;
562
738
}
563
564
//===----------------------------------------------------------------------===//
565
// FileInfo implementation.
566
567
// Safe integer division, returns 0 if numerator is 0.
568
80
static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
569
80
  if (!Numerator)
570
24
    return 0;
571
56
  return Numerator / Divisor;
572
56
}
573
574
// This custom division function mimics gcov's branch ouputs:
575
//   - Round to closest whole number
576
//   - Only output 0% or 100% if it's exactly that value
577
69
static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
578
69
  if (!Numerator)
579
6
    return 0;
580
63
  if (Numerator == Divisor)
581
27
    return 100;
582
36
583
36
  uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor;
584
36
  if (Res == 0)
585
3
    return 1;
586
33
  if (Res == 100)
587
3
    return 99;
588
30
  return Res;
589
30
}
590
591
namespace {
592
struct formatBranchInfo {
593
  formatBranchInfo(const GCOV::Options &Options, uint64_t Count, uint64_t Total)
594
116
      : Options(Options), Count(Count), Total(Total) {}
595
596
116
  void print(raw_ostream &OS) const {
597
116
    if (!Total)
598
8
      OS << "never executed";
599
108
    else if (Options.BranchCount)
600
39
      OS << "taken " << Count;
601
69
    else
602
69
      OS << "taken " << branchDiv(Count, Total) << "%";
603
116
  }
604
605
  const GCOV::Options &Options;
606
  uint64_t Count;
607
  uint64_t Total;
608
};
609
610
116
static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
611
116
  FBI.print(OS);
612
116
  return OS;
613
116
}
614
615
class LineConsumer {
616
  std::unique_ptr<MemoryBuffer> Buffer;
617
  StringRef Remaining;
618
619
public:
620
46
  LineConsumer(StringRef Filename) {
621
46
    ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
622
46
        MemoryBuffer::getFileOrSTDIN(Filename);
623
46
    if (std::error_code EC = BufferOrErr.getError()) {
624
9
      errs() << Filename << ": " << EC.message() << "\n";
625
9
      Remaining = "";
626
37
    } else {
627
37
      Buffer = std::move(BufferOrErr.get());
628
37
      Remaining = Buffer->getBuffer();
629
37
    }
630
46
  }
631
1.64k
  bool empty() { return Remaining.empty(); }
632
1.51k
  void printNext(raw_ostream &OS, uint32_t LineNum) {
633
1.51k
    StringRef Line;
634
1.51k
    if (empty())
635
116
      Line = "/*EOF*/";
636
1.40k
    else
637
1.40k
      std::tie(Line, Remaining) = Remaining.split("\n");
638
1.51k
    OS << format("%5u:", LineNum) << Line << "\n";
639
1.51k
  }
640
};
641
} // end anonymous namespace
642
643
/// Convert a path to a gcov filename. If PreservePaths is true, this
644
/// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
645
42
static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
646
42
  if (!PreservePaths)
647
36
    return sys::path::filename(Filename).str();
648
6
649
6
  // This behaviour is defined by gcov in terms of text replacements, so it's
650
6
  // not likely to do anything useful on filesystems with different textual
651
6
  // conventions.
652
6
  llvm::SmallString<256> Result("");
653
6
  StringRef::iterator I, S, E;
654
174
  for (I = S = Filename.begin(), E = Filename.end(); I != E; 
++I168
) {
655
168
    if (*I != '/')
656
148
      continue;
657
20
658
20
    if (I - S == 1 && 
*S == '.'4
) {
659
4
      // ".", the current directory, is skipped.
660
16
    } else if (I - S == 2 && 
*S == '.'6
&&
*(S + 1) == '.'6
) {
661
6
      // "..", the parent directory, is replaced with "^".
662
6
      Result.append("^#");
663
10
    } else {
664
10
      if (S < I)
665
10
        // Leave other components intact,
666
10
        Result.append(S, I);
667
10
      // And separate with "#".
668
10
      Result.push_back('#');
669
10
    }
670
20
    S = I + 1;
671
20
  }
672
6
673
6
  if (S < I)
674
6
    Result.append(S, I);
675
6
  return Result.str();
676
6
}
677
678
std::string FileInfo::getCoveragePath(StringRef Filename,
679
46
                                      StringRef MainFilename) {
680
46
  if (Options.NoOutput)
681
8
    // This is probably a bug in gcov, but when -n is specified, paths aren't
682
8
    // mangled at all, and the -l and -p options are ignored. Here, we do the
683
8
    // same.
684
8
    return Filename;
685
38
686
38
  std::string CoveragePath;
687
38
  if (Options.LongFileNames && 
!Filename.equals(MainFilename)4
)
688
4
    CoveragePath =
689
4
        mangleCoveragePath(MainFilename, Options.PreservePaths) + "##";
690
38
  CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths);
691
38
  if (Options.HashFilenames) {
692
2
    MD5 Hasher;
693
2
    MD5::MD5Result Result;
694
2
    Hasher.update(Filename.str());
695
2
    Hasher.final(Result);
696
2
    CoveragePath += "##" + Result.digest().str().str();
697
2
  }
698
38
  CoveragePath += ".gcov";
699
38
  return CoveragePath;
700
38
}
701
702
std::unique_ptr<raw_ostream>
703
46
FileInfo::openCoveragePath(StringRef CoveragePath) {
704
46
  if (Options.NoOutput)
705
8
    return llvm::make_unique<raw_null_ostream>();
706
38
707
38
  std::error_code EC;
708
38
  auto OS =
709
38
      llvm::make_unique<raw_fd_ostream>(CoveragePath, EC, sys::fs::F_Text);
710
38
  if (EC) {
711
0
    errs() << EC.message() << "\n";
712
0
    return llvm::make_unique<raw_null_ostream>();
713
0
  }
714
38
  return std::move(OS);
715
38
}
716
717
/// print -  Print source files with collected line count information.
718
void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
719
28
                     StringRef GCNOFile, StringRef GCDAFile) {
720
28
  SmallVector<StringRef, 4> Filenames;
721
28
  for (const auto &LI : LineInfo)
722
46
    Filenames.push_back(LI.first());
723
28
  llvm::sort(Filenames);
724
28
725
46
  for (StringRef Filename : Filenames) {
726
46
    auto AllLines = LineConsumer(Filename);
727
46
728
46
    std::string CoveragePath = getCoveragePath(Filename, MainFilename);
729
46
    std::unique_ptr<raw_ostream> CovStream = openCoveragePath(CoveragePath);
730
46
    raw_ostream &CovOS = *CovStream;
731
46
732
46
    CovOS << "        -:    0:Source:" << Filename << "\n";
733
46
    CovOS << "        -:    0:Graph:" << GCNOFile << "\n";
734
46
    CovOS << "        -:    0:Data:" << GCDAFile << "\n";
735
46
    CovOS << "        -:    0:Runs:" << RunCount << "\n";
736
46
    CovOS << "        -:    0:Programs:" << ProgramCount << "\n";
737
46
738
46
    const LineData &Line = LineInfo[Filename];
739
46
    GCOVCoverage FileCoverage(Filename);
740
1.56k
    for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || 
!AllLines.empty()125
;
741
1.51k
         ++LineIndex) {
742
1.51k
      if (Options.BranchInfo) {
743
308
        FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
744
308
        if (FuncsIt != Line.Functions.end())
745
36
          printFunctionSummary(CovOS, FuncsIt->second);
746
308
      }
747
1.51k
748
1.51k
      BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
749
1.51k
      if (BlocksIt == Line.Blocks.end()) {
750
778
        // No basic blocks are on this line. Not an executable line of code.
751
778
        CovOS << "        -:";
752
778
        AllLines.printNext(CovOS, LineIndex + 1);
753
778
      } else {
754
738
        const BlockVector &Blocks = BlocksIt->second;
755
738
756
738
        // Add up the block counts to form line counts.
757
738
        DenseMap<const GCOVFunction *, bool> LineExecs;
758
938
        for (const GCOVBlock *Block : Blocks) {
759
938
          if (Options.FuncCoverage) {
760
98
            // This is a slightly convoluted way to most accurately gather line
761
98
            // statistics for functions. Basically what is happening is that we
762
98
            // don't want to count a single line with multiple blocks more than
763
98
            // once. However, we also don't simply want to give the total line
764
98
            // count to every function that starts on the line. Thus, what is
765
98
            // happening here are two things:
766
98
            // 1) Ensure that the number of logical lines is only incremented
767
98
            //    once per function.
768
98
            // 2) If there are multiple blocks on the same line, ensure that the
769
98
            //    number of lines executed is incremented as long as at least
770
98
            //    one of the blocks are executed.
771
98
            const GCOVFunction *Function = &Block->getParent();
772
98
            if (FuncCoverages.find(Function) == FuncCoverages.end()) {
773
20
              std::pair<const GCOVFunction *, GCOVCoverage> KeyValue(
774
20
                  Function, GCOVCoverage(Function->getName()));
775
20
              FuncCoverages.insert(KeyValue);
776
20
            }
777
98
            GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
778
98
779
98
            if (LineExecs.find(Function) == LineExecs.end()) {
780
80
              if (Block->getCount()) {
781
68
                ++FuncCoverage.LinesExec;
782
68
                LineExecs[Function] = true;
783
68
              } else {
784
12
                LineExecs[Function] = false;
785
12
              }
786
80
              ++FuncCoverage.LogicalLines;
787
80
            } else 
if (18
!LineExecs[Function]18
&&
Block->getCount()0
) {
788
0
              ++FuncCoverage.LinesExec;
789
0
              LineExecs[Function] = true;
790
0
            }
791
98
          }
792
938
        }
793
738
794
738
        const uint64_t LineCount = GCOVBlock::getLineCount(Blocks);
795
738
        if (LineCount == 0)
796
165
          CovOS << "    #####:";
797
573
        else {
798
573
          CovOS << format("%9" PRIu64 ":", LineCount);
799
573
          ++FileCoverage.LinesExec;
800
573
        }
801
738
        ++FileCoverage.LogicalLines;
802
738
803
738
        AllLines.printNext(CovOS, LineIndex + 1);
804
738
805
738
        uint32_t BlockNo = 0;
806
738
        uint32_t EdgeNo = 0;
807
938
        for (const GCOVBlock *Block : Blocks) {
808
938
          // Only print block and branch information at the end of the block.
809
938
          if (Block->getLastLine() != LineIndex + 1)
810
283
            continue;
811
655
          if (Options.AllBlocks)
812
170
            printBlockInfo(CovOS, *Block, LineIndex, BlockNo);
813
655
          if (Options.BranchInfo) {
814
136
            size_t NumEdges = Block->getNumDstEdges();
815
136
            if (NumEdges > 1)
816
24
              printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
817
112
            else if (Options.UncondBranch && 
NumEdges == 156
)
818
56
              printUncondBranchInfo(CovOS, EdgeNo,
819
56
                                    (*Block->dst_begin())->Count);
820
136
          }
821
655
        }
822
738
      }
823
1.51k
    }
824
46
    FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
825
46
  }
826
28
827
28
  // FIXME: There is no way to detect calls given current instrumentation.
828
28
  if (Options.FuncCoverage)
829
2
    printFuncCoverage(InfoOS);
830
28
  printFileCoverage(InfoOS);
831
28
}
832
833
/// printFunctionSummary - Print function and block summary.
834
void FileInfo::printFunctionSummary(raw_ostream &OS,
835
36
                                    const FunctionVector &Funcs) const {
836
40
  for (const GCOVFunction *Func : Funcs) {
837
40
    uint64_t EntryCount = Func->getEntryCount();
838
40
    uint32_t BlocksExec = 0;
839
40
    for (const GCOVBlock &Block : Func->blocks())
840
216
      if (Block.getNumDstEdges() && 
Block.getCount()176
)
841
148
        ++BlocksExec;
842
40
843
40
    OS << "function " << Func->getName() << " called " << EntryCount
844
40
       << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount)
845
40
       << "% blocks executed "
846
40
       << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n";
847
40
  }
848
36
}
849
850
/// printBlockInfo - Output counts for each block.
851
void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
852
170
                              uint32_t LineIndex, uint32_t &BlockNo) const {
853
170
  if (Block.getCount() == 0)
854
20
    OS << "    $$$$$:";
855
150
  else
856
150
    OS << format("%9" PRIu64 ":", Block.getCount());
857
170
  OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++);
858
170
}
859
860
/// printBranchInfo - Print conditional branch probabilities.
861
void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
862
24
                               GCOVCoverage &Coverage, uint32_t &EdgeNo) {
863
24
  SmallVector<uint64_t, 16> BranchCounts;
864
24
  uint64_t TotalCounts = 0;
865
60
  for (const GCOVEdge *Edge : Block.dsts()) {
866
60
    BranchCounts.push_back(Edge->Count);
867
60
    TotalCounts += Edge->Count;
868
60
    if (Block.getCount())
869
60
      ++Coverage.BranchesExec;
870
60
    if (Edge->Count)
871
52
      ++Coverage.BranchesTaken;
872
60
    ++Coverage.Branches;
873
60
874
60
    if (Options.FuncCoverage) {
875
15
      const GCOVFunction *Function = &Block.getParent();
876
15
      GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
877
15
      if (Block.getCount())
878
15
        ++FuncCoverage.BranchesExec;
879
15
      if (Edge->Count)
880
13
        ++FuncCoverage.BranchesTaken;
881
15
      ++FuncCoverage.Branches;
882
15
    }
883
60
  }
884
24
885
24
  for (uint64_t N : BranchCounts)
886
60
    OS << format("branch %2u ", EdgeNo++)
887
60
       << formatBranchInfo(Options, N, TotalCounts) << "\n";
888
24
}
889
890
/// printUncondBranchInfo - Print unconditional branch probabilities.
891
void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
892
56
                                     uint64_t Count) const {
893
56
  OS << format("unconditional %2u ", EdgeNo++)
894
56
     << formatBranchInfo(Options, Count, Count) << "\n";
895
56
}
896
897
// printCoverage - Print generic coverage info used by both printFuncCoverage
898
// and printFileCoverage.
899
void FileInfo::printCoverage(raw_ostream &OS,
900
66
                             const GCOVCoverage &Coverage) const {
901
66
  OS << format("Lines executed:%.2f%% of %u\n",
902
66
               double(Coverage.LinesExec) * 100 / Coverage.LogicalLines,
903
66
               Coverage.LogicalLines);
904
66
  if (Options.BranchInfo) {
905
18
    if (Coverage.Branches) {
906
6
      OS << format("Branches executed:%.2f%% of %u\n",
907
6
                   double(Coverage.BranchesExec) * 100 / Coverage.Branches,
908
6
                   Coverage.Branches);
909
6
      OS << format("Taken at least once:%.2f%% of %u\n",
910
6
                   double(Coverage.BranchesTaken) * 100 / Coverage.Branches,
911
6
                   Coverage.Branches);
912
12
    } else {
913
12
      OS << "No branches\n";
914
12
    }
915
18
    OS << "No calls\n"; // to be consistent with gcov
916
18
  }
917
66
}
918
919
// printFuncCoverage - Print per-function coverage info.
920
2
void FileInfo::printFuncCoverage(raw_ostream &OS) const {
921
20
  for (const auto &FC : FuncCoverages) {
922
20
    const GCOVCoverage &Coverage = FC.second;
923
20
    OS << "Function '" << Coverage.Name << "'\n";
924
20
    printCoverage(OS, Coverage);
925
20
    OS << "\n";
926
20
  }
927
2
}
928
929
// printFileCoverage - Print per-file coverage info.
930
28
void FileInfo::printFileCoverage(raw_ostream &OS) const {
931
46
  for (const auto &FC : FileCoverages) {
932
46
    const std::string &Filename = FC.first;
933
46
    const GCOVCoverage &Coverage = FC.second;
934
46
    OS << "File '" << Coverage.Name << "'\n";
935
46
    printCoverage(OS, Coverage);
936
46
    if (!Options.NoOutput)
937
38
      OS << Coverage.Name << ":creating '" << Filename << "'\n";
938
46
    OS << "\n";
939
46
  }
940
28
}