LLVM API Documentation
00001 //===- GCOV.h - LLVM coverage tool ----------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This header provides the interface to read and write coverage files that 00011 // use 'gcov' format. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_SUPPORT_GCOV_H 00016 #define LLVM_SUPPORT_GCOV_H 00017 00018 #include "llvm/ADT/DenseMap.h" 00019 #include "llvm/ADT/MapVector.h" 00020 #include "llvm/ADT/SmallVector.h" 00021 #include "llvm/ADT/StringMap.h" 00022 #include "llvm/Support/MemoryBuffer.h" 00023 #include "llvm/Support/raw_ostream.h" 00024 00025 namespace llvm { 00026 00027 class GCOVFunction; 00028 class GCOVBlock; 00029 class FileInfo; 00030 00031 namespace GCOV { 00032 enum GCOVVersion { 00033 V402, 00034 V404 00035 }; 00036 } // end GCOV namespace 00037 00038 /// GCOVOptions - A struct for passing gcov options between functions. 00039 struct GCOVOptions { 00040 GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) 00041 : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), 00042 PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} 00043 00044 bool AllBlocks; 00045 bool BranchInfo; 00046 bool BranchCount; 00047 bool FuncCoverage; 00048 bool PreservePaths; 00049 bool UncondBranch; 00050 bool LongFileNames; 00051 bool NoOutput; 00052 }; 00053 00054 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific 00055 /// read operations. 00056 class GCOVBuffer { 00057 public: 00058 GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} 00059 00060 /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. 00061 bool readGCNOFormat() { 00062 StringRef File = Buffer->getBuffer().slice(0, 4); 00063 if (File != "oncg") { 00064 errs() << "Unexpected file type: " << File << ".\n"; 00065 return false; 00066 } 00067 Cursor = 4; 00068 return true; 00069 } 00070 00071 /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. 00072 bool readGCDAFormat() { 00073 StringRef File = Buffer->getBuffer().slice(0, 4); 00074 if (File != "adcg") { 00075 errs() << "Unexpected file type: " << File << ".\n"; 00076 return false; 00077 } 00078 Cursor = 4; 00079 return true; 00080 } 00081 00082 /// readGCOVVersion - Read GCOV version. 00083 bool readGCOVVersion(GCOV::GCOVVersion &Version) { 00084 StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4); 00085 if (VersionStr == "*204") { 00086 Cursor += 4; 00087 Version = GCOV::V402; 00088 return true; 00089 } 00090 if (VersionStr == "*404") { 00091 Cursor += 4; 00092 Version = GCOV::V404; 00093 return true; 00094 } 00095 errs() << "Unexpected version: " << VersionStr << ".\n"; 00096 return false; 00097 } 00098 00099 /// readFunctionTag - If cursor points to a function tag then increment the 00100 /// cursor and return true otherwise return false. 00101 bool readFunctionTag() { 00102 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00103 if (Tag.empty() || 00104 Tag[0] != '\0' || Tag[1] != '\0' || 00105 Tag[2] != '\0' || Tag[3] != '\1') { 00106 return false; 00107 } 00108 Cursor += 4; 00109 return true; 00110 } 00111 00112 /// readBlockTag - If cursor points to a block tag then increment the 00113 /// cursor and return true otherwise return false. 00114 bool readBlockTag() { 00115 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00116 if (Tag.empty() || 00117 Tag[0] != '\0' || Tag[1] != '\0' || 00118 Tag[2] != '\x41' || Tag[3] != '\x01') { 00119 return false; 00120 } 00121 Cursor += 4; 00122 return true; 00123 } 00124 00125 /// readEdgeTag - If cursor points to an edge tag then increment the 00126 /// cursor and return true otherwise return false. 00127 bool readEdgeTag() { 00128 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00129 if (Tag.empty() || 00130 Tag[0] != '\0' || Tag[1] != '\0' || 00131 Tag[2] != '\x43' || Tag[3] != '\x01') { 00132 return false; 00133 } 00134 Cursor += 4; 00135 return true; 00136 } 00137 00138 /// readLineTag - If cursor points to a line tag then increment the 00139 /// cursor and return true otherwise return false. 00140 bool readLineTag() { 00141 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00142 if (Tag.empty() || 00143 Tag[0] != '\0' || Tag[1] != '\0' || 00144 Tag[2] != '\x45' || Tag[3] != '\x01') { 00145 return false; 00146 } 00147 Cursor += 4; 00148 return true; 00149 } 00150 00151 /// readArcTag - If cursor points to an gcda arc tag then increment the 00152 /// cursor and return true otherwise return false. 00153 bool readArcTag() { 00154 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00155 if (Tag.empty() || 00156 Tag[0] != '\0' || Tag[1] != '\0' || 00157 Tag[2] != '\xa1' || Tag[3] != '\1') { 00158 return false; 00159 } 00160 Cursor += 4; 00161 return true; 00162 } 00163 00164 /// readObjectTag - If cursor points to an object summary tag then increment 00165 /// the cursor and return true otherwise return false. 00166 bool readObjectTag() { 00167 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00168 if (Tag.empty() || 00169 Tag[0] != '\0' || Tag[1] != '\0' || 00170 Tag[2] != '\0' || Tag[3] != '\xa1') { 00171 return false; 00172 } 00173 Cursor += 4; 00174 return true; 00175 } 00176 00177 /// readProgramTag - If cursor points to a program summary tag then increment 00178 /// the cursor and return true otherwise return false. 00179 bool readProgramTag() { 00180 StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); 00181 if (Tag.empty() || 00182 Tag[0] != '\0' || Tag[1] != '\0' || 00183 Tag[2] != '\0' || Tag[3] != '\xa3') { 00184 return false; 00185 } 00186 Cursor += 4; 00187 return true; 00188 } 00189 00190 bool readInt(uint32_t &Val) { 00191 if (Buffer->getBuffer().size() < Cursor+4) { 00192 errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n"; 00193 return false; 00194 } 00195 StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); 00196 Cursor += 4; 00197 Val = *(const uint32_t *)(Str.data()); 00198 return true; 00199 } 00200 00201 bool readInt64(uint64_t &Val) { 00202 uint32_t Lo, Hi; 00203 if (!readInt(Lo) || !readInt(Hi)) return false; 00204 Val = ((uint64_t)Hi << 32) | Lo; 00205 return true; 00206 } 00207 00208 bool readString(StringRef &Str) { 00209 uint32_t Len = 0; 00210 // Keep reading until we find a non-zero length. This emulates gcov's 00211 // behaviour, which appears to do the same. 00212 while (Len == 0) 00213 if (!readInt(Len)) return false; 00214 Len *= 4; 00215 if (Buffer->getBuffer().size() < Cursor+Len) { 00216 errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n"; 00217 return false; 00218 } 00219 Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first; 00220 Cursor += Len; 00221 return true; 00222 } 00223 00224 uint64_t getCursor() const { return Cursor; } 00225 void advanceCursor(uint32_t n) { Cursor += n*4; } 00226 private: 00227 MemoryBuffer *Buffer; 00228 uint64_t Cursor; 00229 }; 00230 00231 /// GCOVFile - Collects coverage information for one pair of coverage file 00232 /// (.gcno and .gcda). 00233 class GCOVFile { 00234 public: 00235 GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), 00236 ProgramCount(0) {} 00237 bool readGCNO(GCOVBuffer &Buffer); 00238 bool readGCDA(GCOVBuffer &Buffer); 00239 uint32_t getChecksum() const { return Checksum; } 00240 void dump() const; 00241 void collectLineCounts(FileInfo &FI); 00242 private: 00243 bool GCNOInitialized; 00244 GCOV::GCOVVersion Version; 00245 uint32_t Checksum; 00246 SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions; 00247 uint32_t RunCount; 00248 uint32_t ProgramCount; 00249 }; 00250 00251 /// GCOVEdge - Collects edge information. 00252 struct GCOVEdge { 00253 GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {} 00254 00255 GCOVBlock &Src; 00256 GCOVBlock &Dst; 00257 uint64_t Count; 00258 }; 00259 00260 /// GCOVFunction - Collects function information. 00261 class GCOVFunction { 00262 public: 00263 typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator 00264 BlockIterator; 00265 00266 GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {} 00267 bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); 00268 bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); 00269 StringRef getName() const { return Name; } 00270 StringRef getFilename() const { return Filename; } 00271 size_t getNumBlocks() const { return Blocks.size(); } 00272 uint64_t getEntryCount() const; 00273 uint64_t getExitCount() const; 00274 00275 BlockIterator block_begin() const { return Blocks.begin(); } 00276 BlockIterator block_end() const { return Blocks.end(); } 00277 00278 void dump() const; 00279 void collectLineCounts(FileInfo &FI); 00280 private: 00281 GCOVFile &Parent; 00282 uint32_t Ident; 00283 uint32_t Checksum; 00284 uint32_t LineNumber; 00285 StringRef Name; 00286 StringRef Filename; 00287 SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks; 00288 SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges; 00289 }; 00290 00291 /// GCOVBlock - Collects block information. 00292 class GCOVBlock { 00293 struct EdgeWeight { 00294 EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {} 00295 00296 GCOVBlock *Dst; 00297 uint64_t Count; 00298 }; 00299 00300 struct SortDstEdgesFunctor { 00301 bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) { 00302 return E1->Dst.Number < E2->Dst.Number; 00303 } 00304 }; 00305 public: 00306 typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator; 00307 00308 GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0), 00309 DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {} 00310 ~GCOVBlock(); 00311 const GCOVFunction &getParent() const { return Parent; } 00312 void addLine(uint32_t N) { Lines.push_back(N); } 00313 uint32_t getLastLine() const { return Lines.back(); } 00314 void addCount(size_t DstEdgeNo, uint64_t N); 00315 uint64_t getCount() const { return Counter; } 00316 00317 void addSrcEdge(GCOVEdge *Edge) { 00318 assert(&Edge->Dst == this); // up to caller to ensure edge is valid 00319 SrcEdges.push_back(Edge); 00320 } 00321 void addDstEdge(GCOVEdge *Edge) { 00322 assert(&Edge->Src == this); // up to caller to ensure edge is valid 00323 // Check if adding this edge causes list to become unsorted. 00324 if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number) 00325 DstEdgesAreSorted = false; 00326 DstEdges.push_back(Edge); 00327 } 00328 size_t getNumSrcEdges() const { return SrcEdges.size(); } 00329 size_t getNumDstEdges() const { return DstEdges.size(); } 00330 void sortDstEdges(); 00331 00332 EdgeIterator src_begin() const { return SrcEdges.begin(); } 00333 EdgeIterator src_end() const { return SrcEdges.end(); } 00334 EdgeIterator dst_begin() const { return DstEdges.begin(); } 00335 EdgeIterator dst_end() const { return DstEdges.end(); } 00336 00337 void dump() const; 00338 void collectLineCounts(FileInfo &FI); 00339 private: 00340 GCOVFunction &Parent; 00341 uint32_t Number; 00342 uint64_t Counter; 00343 bool DstEdgesAreSorted; 00344 SmallVector<GCOVEdge *, 16> SrcEdges; 00345 SmallVector<GCOVEdge *, 16> DstEdges; 00346 SmallVector<uint32_t, 16> Lines; 00347 }; 00348 00349 class FileInfo { 00350 // It is unlikely--but possible--for multiple functions to be on the same line. 00351 // Therefore this typedef allows LineData.Functions to store multiple functions 00352 // per instance. This is rare, however, so optimize for the common case. 00353 typedef SmallVector<const GCOVFunction *, 1> FunctionVector; 00354 typedef DenseMap<uint32_t, FunctionVector> FunctionLines; 00355 typedef SmallVector<const GCOVBlock *, 4> BlockVector; 00356 typedef DenseMap<uint32_t, BlockVector> BlockLines; 00357 00358 struct LineData { 00359 LineData() : LastLine(0) {} 00360 BlockLines Blocks; 00361 FunctionLines Functions; 00362 uint32_t LastLine; 00363 }; 00364 00365 struct GCOVCoverage { 00366 GCOVCoverage(StringRef Name) : 00367 Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0), 00368 BranchesTaken(0) {} 00369 00370 StringRef Name; 00371 00372 uint32_t LogicalLines; 00373 uint32_t LinesExec; 00374 00375 uint32_t Branches; 00376 uint32_t BranchesExec; 00377 uint32_t BranchesTaken; 00378 }; 00379 public: 00380 FileInfo(const GCOVOptions &Options) : 00381 Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} 00382 00383 void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { 00384 if (Line > LineInfo[Filename].LastLine) 00385 LineInfo[Filename].LastLine = Line; 00386 LineInfo[Filename].Blocks[Line-1].push_back(Block); 00387 } 00388 void addFunctionLine(StringRef Filename, uint32_t Line, 00389 const GCOVFunction *Function) { 00390 if (Line > LineInfo[Filename].LastLine) 00391 LineInfo[Filename].LastLine = Line; 00392 LineInfo[Filename].Functions[Line-1].push_back(Function); 00393 } 00394 void setRunCount(uint32_t Runs) { RunCount = Runs; } 00395 void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } 00396 void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); 00397 00398 private: 00399 std::string getCoveragePath(StringRef Filename, StringRef MainFilename); 00400 std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); 00401 void printFunctionSummary(raw_ostream &OS, 00402 const FunctionVector &Funcs) const; 00403 void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, 00404 uint32_t LineIndex, uint32_t &BlockNo) const; 00405 void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, 00406 GCOVCoverage &Coverage, uint32_t &EdgeNo); 00407 void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, 00408 uint64_t Count) const; 00409 00410 void printCoverage(const GCOVCoverage &Coverage) const; 00411 void printFuncCoverage() const; 00412 void printFileCoverage() const; 00413 00414 const GCOVOptions &Options; 00415 StringMap<LineData> LineInfo; 00416 uint32_t RunCount; 00417 uint32_t ProgramCount; 00418 00419 typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> 00420 FileCoverageList; 00421 typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap; 00422 00423 FileCoverageList FileCoverages; 00424 FuncCoverageMap FuncCoverages; 00425 }; 00426 00427 } 00428 00429 #endif