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