[llvm-commits] [llvm] r140712 - in /llvm/trunk/tools: Makefile llvm-cov/ llvm-cov/CMakeLists.txt llvm-cov/GCOVReader.cpp llvm-cov/GCOVReader.h llvm-cov/Makefile llvm-cov/llvm-cov.cpp
Nick Lewycky
nlewycky at google.com
Wed Sep 28 18:01:34 PDT 2011
On 28 September 2011 11:50, Devang Patel <dpatel at apple.com> wrote:
> Author: dpatel
> Date: Wed Sep 28 13:50:00 2011
> New Revision: 140712
>
> URL: http://llvm.org/viewvc/llvm-project?rev=140712&view=rev
> Log:
> Introduce llvm-cov.
Cool!!
At a high-level, is there any interest in creating a GCOV data storage
for reading/manipulating/writing? I didn't think anyone would ever
need to write llvm-cov, so I decided to make GCOVProfiling write-only,
but you have types with the same name here.
> Add llvm-cov skeleton. It has initial support to read coverage info generated by GCOVProfiling.cpp.
> Today, you can do
> prompt> clang a.c -ftest-coverage -fprofile-arcs -o a
> prompt> ./a
> prompt> llvm-cov -gcno a.gcno -gcda a.gcda
> a.c
> : #include "a.h"
> :
> : int main() {
> : int i = 0;
> : if (i) {
> 1: int j = 0;
> 1: j = 1;
> 1: } else {
> : int k = 1;
> : k = 2;
> : }
> 1: return 0;
> : }
> :
> :
>
>
>
> Added:
> llvm/trunk/tools/llvm-cov/
> llvm/trunk/tools/llvm-cov/CMakeLists.txt
> llvm/trunk/tools/llvm-cov/GCOVReader.cpp
> llvm/trunk/tools/llvm-cov/GCOVReader.h
> llvm/trunk/tools/llvm-cov/Makefile
> llvm/trunk/tools/llvm-cov/llvm-cov.cpp
> Modified:
> llvm/trunk/tools/Makefile
>
> Modified: llvm/trunk/tools/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=140712&r1=140711&r2=140712&view=diff
> ==============================================================================
> --- llvm/trunk/tools/Makefile (original)
> +++ llvm/trunk/tools/Makefile Wed Sep 28 13:50:00 2011
> @@ -26,7 +26,7 @@
> lli llvm-extract llvm-mc \
> bugpoint llvm-bcanalyzer llvm-stub \
> llvm-diff macho-dump llvm-objdump \
> - llvm-rtdyld llvm-dwarfdump
> + llvm-rtdyld llvm-dwarfdump llvm-cov
>
> # Let users override the set of tools to build from the command line.
> ifdef ONLY_TOOLS
>
> Added: llvm/trunk/tools/llvm-cov/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CMakeLists.txt?rev=140712&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-cov/CMakeLists.txt (added)
> +++ llvm/trunk/tools/llvm-cov/CMakeLists.txt Wed Sep 28 13:50:00 2011
> @@ -0,0 +1,6 @@
> +set(LLVM_LINK_COMPONENTS instrumentation )
> +
> +add_llvm_tool(llvm-cov
> + GCOVReader.cpp
> + llvm-cov.cpp
> + )
>
> Added: llvm/trunk/tools/llvm-cov/GCOVReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/GCOVReader.cpp?rev=140712&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-cov/GCOVReader.cpp (added)
> +++ llvm/trunk/tools/llvm-cov/GCOVReader.cpp Wed Sep 28 13:50:00 2011
> @@ -0,0 +1,276 @@
> +//===- tools/llvm-cov/GCOVReader.cpp - LLVM coverage tool -----------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// GCOVReader implements the interface to read coverage files that use 'gcov'
> +// format.
> +//
> +//
Extra // line.
> +//===----------------------------------------------------------------------===//
> +
> +#include "GCOVReader.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/ADT/OwningPtr.h"
Alphabetize.
> +#include "llvm/Support/MemoryObject.h"
> +#include "llvm/Support/system_error.h"
> +using namespace llvm;
> +
> +//===----------------------------------------------------------------------===//
> +// GCOVFile implementation.
> +
> +/// ~GCOVFile - Delete GCOVFile and its content.
> +GCOVFile::~GCOVFile() {
> + DeleteContainerPointers(Functions);
> +}
> +
> +/// read - Read GCOV buffer.
> +bool GCOVFile::read(GCOVBuffer &Buffer) {
> + Format = Buffer.readGCOVFormat();
> + if (Format == InvalidGCOV)
> + return false;
> +
> + unsigned i = 0;
> + while(1) {
"while(" --> "while (".
> + GCOVFunction *GFun = NULL;
> + if(Format == GCDA_402 || Format == GCDA_404) {
"if(" --> "if (".
> + if (i < Functions.size())
> + GFun = Functions[i];
> + } else
> + GFun = new GCOVFunction();
> +
> + if (GFun && GFun->read(Buffer, Format)) {
> + if(Format == GCNO_402 || Format == GCNO_404)
"if(" --> "if (".
> + Functions.push_back(GFun);
> + }
> + else {
> + delete GFun;
> + break;
> + }
> + ++i;
> + }
This is a really confusing loop. In concept, I would've liked an outer
loop that does:
tag = readTag();
size = readSize();
switch (tag) {
case FUNCTION_TAG: ... break;
case EOF_TAG: return;
default: skip_block(size);
}
with additional checks to quit when the EOF was reached (without EOF
tag). However, keeping along the lines of the way it works now, I
think you could do:
int i = 0;
while (1) {
if (i > Functions.size())
Functions.push_back(NULL);
GCOVFunction *&GFun = Functions.back();
if (!GFun) GFun = new GCOVFunction();
if (!GFun->read(Buffer, Format)) {
delete GFun;
GFun = 0;
return true;
}
}
I think that's clearer. Does that work?
> + return true;
> +}
> +
> +/// dump - Dump GCOVFile content on standard out for debugging purposes.
> +void GCOVFile::dump() {
> + for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(),
> + E = Functions.end(); I != E; ++I)
> + (*I)->dump();
> +}
> +
> +/// collectLineCounts - Collect line counts. This must be used after
> +/// reading .gcno and .gcda files.
> +void GCOVFile::collectLineCounts(FileInfo &FI) {
> + for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(),
> + E = Functions.end(); I != E; ++I)
> + (*I)->collectLineCounts(FI);
> + FI.print();
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// GCOVFunction implementation.
> +
> +/// ~GCOVFunction - Delete GCOVFunction and its content.
> +GCOVFunction::~GCOVFunction() {
> + DeleteContainerPointers(Blocks);
> +}
> +
> +/// read - Read a aunction from the buffer. Return false if buffer cursor
Typo: "aunction" --> "function".
> +/// does not point to a function tag.
> +bool GCOVFunction::read(GCOVBuffer &Buff, GCOVFormat Format) {
> + if (!Buff.readFunctionTag())
> + return false;
> +
> + Buff.readInt(); // Function header length
> + Ident = Buff.readInt();
> + Buff.readInt(); // Checksum #1
> + if (Format != GCNO_402)
> + Buff.readInt(); // Checksum #2
> +
> + Name = Buff.readString();
> + if(Format == GCNO_402 || Format == GCNO_404)
"if(" --> "if (".
> + Filename = Buff.readString();
> +
> + if(Format == GCDA_402 || Format == GCDA_404) {
"if(" --> "if (".
> + Buff.readArcTag();
> + uint32_t Count = Buff.readInt() / 2;
> + for (unsigned i = 0, e = Count; i != e; ++i) {
> + Blocks[i]->addCount(Buff.readInt64());
> + }
> + return true;;
Bonus semicolon.
> + }
> +
> + LineNumber = Buff.readInt();
> +
> + // read blocks.
> + assert (Buff.readBlockTag() && "Block Tag not found!");
"assert (" --> "assert(".
> + uint32_t BlockCount = Buff.readInt();
> + for (int i = 0, e = BlockCount; i != e; ++i) {
> + Buff.readInt(); // Block flags;
> + Blocks.push_back(new GCOVBlock(i));
> + }
> +
> + // read edges.
> + while (Buff.readEdgeTag()) {
> + uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
> + uint32_t BlockNo = Buff.readInt();
> + assert (BlockNo < BlockCount && "Unexpected Block number!");
"assert (" --> "assert(".
> + for (int i = 0, e = EdgeCount; i != e; ++i) {
> + Blocks[BlockNo]->addEdge(Buff.readInt());
> + Buff.readInt(); // Edge flag
> + }
> + }
> +
> + // read line table.
> + while (Buff.readLineTag()) {
> + uint32_t LineTableLength = Buff.readInt();
> + uint32_t Size = Buff.getCursor() + LineTableLength*4;
It's not the size though, that's the EndCursor.
> + uint32_t BlockNo = Buff.readInt();
> + assert (BlockNo < BlockCount && "Unexpected Block number!");
"assert (" --> "assert("
> + GCOVBlock *Block = Blocks[BlockNo];
> + Buff.readInt(); // flag
> + while (Buff.getCursor() != (Size - 4)) {
> + StringRef Filename = Buff.readString();
> + if (Buff.getCursor() == (Size - 4)) break;
> + while (uint32_t L = Buff.readInt())
> + Block->addLine(Filename, L);
> + }
> + Buff.readInt(); // flag
> + }
> + return true;
> +}
> +
> +/// dump - Dump GCOVFunction content on standard out for debugging purposes.
> +void GCOVFunction::dump() {
> + outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
> + for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(),
> + E = Blocks.end(); I != E; ++I)
> + (*I)->dump();
> +}
> +
> +/// collectLineCounts - Collect line counts. This must be used after
> +/// reading .gcno and .gcda files.
> +void GCOVFunction::collectLineCounts(FileInfo &FI) {
> + for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(),
> + E = Blocks.end(); I != E; ++I)
> + (*I)->collectLineCounts(FI);
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// GCOVBlock implementation.
> +
> +/// ~GCOVBlock - Delete GCOVBlock and its content.
> +GCOVBlock::~GCOVBlock() {
> + Edges.clear();
> + DeleteContainerSeconds(Lines);
> +}
> +
> +void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) {
> + GCOVLines *&LinesForFile = Lines[Filename];
> + if (!LinesForFile)
> + LinesForFile = new GCOVLines();
> + LinesForFile->add(LineNo);
> +}
> +
> +/// collectLineCounts - Collect line counts. This must be used after
> +/// reading .gcno and .gcda files.
> +void GCOVBlock::collectLineCounts(FileInfo &FI) {
> + for (StringMap<GCOVLines *>::iterator I = Lines.begin(),
> + E = Lines.end(); I != E; ++I)
> + I->second->collectLineCounts(FI, I->first(), Counter);
> +}
> +
> +/// dump - Dump GCOVBlock content on standard out for debugging purposes.
> +void GCOVBlock::dump() {
> + outs() << "Block : " << Number << " Counter : " << Counter << "\n";
> + if (!Edges.empty()) {
> + outs() << "\tEdges : ";
> + for (SmallVector<uint32_t, 16>::iterator I = Edges.begin(), E = Edges.end();
> + I != E; ++I)
> + outs() << (*I) << ",";
> + outs() << "\n";
> + }
> + if (!Lines.empty()) {
> + outs() << "\tLines : ";
> + for (StringMap<GCOVLines *>::iterator LI = Lines.begin(),
> + LE = Lines.end(); LI != LE; ++LI) {
> + outs() << LI->first() << " -> ";
> + LI->second->dump();
> + outs() << "\n";
> + }
> + }
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// GCOVLines implementation.
> +
> +/// collectLineCounts - Collect line counts. This must be used after
> +/// reading .gcno and .gcda files.
> +void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename,
> + uint32_t Count) {
> + for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(),
> + E = Lines.end(); I != E; ++I)
> + FI.addLineCount(Filename, *I, Count);
> +}
> +
> +/// dump - Dump GCOVLines content on standard out for debugging purposes.
> +void GCOVLines::dump() {
> + for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(),
> + E = Lines.end(); I != E; ++I)
> + outs() << (*I) << ",";
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// FileInfo implementation.
> +
> +/// addLineCount - Add line count for the given line number in a file.
> +void FileInfo::addLineCount(StringRef Filename, uint32_t Line, uint32_t Count) {
> + if (LineInfo.find(Filename) == LineInfo.end()) {
> + OwningPtr<MemoryBuffer> Buff;
> + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
> + errs() << Filename << ": " << ec.message() << "\n";
> + return;
> + }
> + StringRef AllLines = Buff.take()->getBuffer();
> + LineCounts L(AllLines.count('\n')+2);
> + L[Line-1] = Count;
> + LineInfo[Filename] = L;
> + return;
> + }
> + LineCounts &L = LineInfo[Filename];
> + L[Line-1] = Count;
> +}
> +
> +/// print - Print source files with collected line count information.
> +void FileInfo::print() {
> + for (StringMap<LineCounts>::iterator I = LineInfo.begin(), E = LineInfo.end();
> + I != E; ++I) {
> + StringRef Filename = I->first();
> + outs() << Filename << "\n";
> + LineCounts &L = LineInfo[Filename];
> + OwningPtr<MemoryBuffer> Buff;
> + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
> + errs() << Filename << ": " << ec.message() << "\n";
> + return;
> + }
> + StringRef AllLines = Buff.take()->getBuffer();
> + for (unsigned i = 0, e = L.size(); i != e; ++i) {
> + if (L[i])
> + outs() << L[i] << ":\t";
> + else
> + outs() << " :\t";
> + std::pair<StringRef, StringRef> P = AllLines.split('\n');
> + if (AllLines != P.first)
> + outs() << P.first;
> + outs() << "\n";
> + AllLines = P.second;
> + }
> + }
> +}
> +
> +
>
> Added: llvm/trunk/tools/llvm-cov/GCOVReader.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/GCOVReader.h?rev=140712&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-cov/GCOVReader.h (added)
> +++ llvm/trunk/tools/llvm-cov/GCOVReader.h Wed Sep 28 13:50:00 2011
> @@ -0,0 +1,225 @@
> +//===-- tools/cov/GCOVReader.h - LLVM coverage tool -------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This header provides the interface to read coverage files that use 'gcov'
> +// format.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef GCOVREADER_H
> +#define GCOVREADER_H
Optional: LLVMCOV_GCOVREADER_H.
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +namespace llvm {
> +
> +class GCOVFunction;
> +class GCOVBlock;
> +class GCOVLines;
> +class FileInfo;
> +
> +enum GCOVFormat {
> + InvalidGCOV,
> + GCNO_402,
> + GCNO_404,
> + GCDA_402,
> + GCDA_404
> +};
> +
> +/// GCOVBuffer - A wrapper around MemoryBuffer to provid GCOV specific
Typo, "provid" -> "provide".
> +/// read operations.
> +class GCOVBuffer {
> +public:
> + GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
> +
> + /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
> + enum GCOVFormat readGCOVFormat() {
> + StringRef Magic = Buffer->getBuffer().slice(0, 12);
> + Cursor = 12;
> + if (Magic == "oncg*404MVLL")
> + return GCNO_404;
> + else if (Magic == "oncg*204MVLL")
> + return GCNO_402;
> + else if (Magic == "adcg*404MVLL")
> + return GCDA_404;
> + else if (Magic == "adcg*204MVLL")
> + return GCDA_402;
Do we really want to check the "LLVM" part? With this, we can't read
GCC-produced .gcov files, and that really limits how useful this code
can ever be. In particular, we can't test it against gcc-generated
gcov files.
> +
> + Cursor = 0;
> + return InvalidGCOV;
> + }
> +
> + /// readFunctionTag - If cursor points to a function tag then increment the
> + /// cursor and return true otherwise return false.
> + bool readFunctionTag() {
> + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
> + if (Tag.empty() ||
> + Tag[0] != '\0' || Tag[1] != '\0' ||
> + Tag[2] != '\0' || Tag[3] != '\1') {
> + return false;
> + }
> + Cursor += 4;
> + return true;
> + }
> +
> + /// readBlockTag - If cursor points to a block tag then increment the
> + /// cursor and return true otherwise return false.
> + bool readBlockTag() {
> + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
> + if (Tag.empty() ||
> + Tag[0] != '\0' || Tag[1] != '\0' ||
> + Tag[2] != '\x41' || Tag[3] != '\x01') {
> + return false;
> + }
> + Cursor += 4;
> + return true;
> + }
> +
> + /// readEdgeTag - If cursor points to an edge tag then increment the
> + /// cursor and return true otherwise return false.
> + bool readEdgeTag() {
> + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
> + if (Tag.empty() ||
> + Tag[0] != '\0' || Tag[1] != '\0' ||
> + Tag[2] != '\x43' || Tag[3] != '\x01') {
> + return false;
> + }
> + Cursor += 4;
> + return true;
> + }
> +
> + /// readLineTag - If cursor points to a line tag then increment the
> + /// cursor and return true otherwise return false.
> + bool readLineTag() {
> + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
> + if (Tag.empty() ||
> + Tag[0] != '\0' || Tag[1] != '\0' ||
> + Tag[2] != '\x45' || Tag[3] != '\x01') {
> + return false;
> + }
> + Cursor += 4;
> + return true;
> + }
> +
> + /// readArcTag - If cursor points to an gcda arc tag then increment the
> + /// cursor and return true otherwise return false.
> + bool readArcTag() {
> + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
> + if (Tag.empty() ||
> + Tag[0] != '\0' || Tag[1] != '\0' ||
> + Tag[2] != '\xa1' || Tag[3] != '\1') {
> + return false;
> + }
> + Cursor += 4;
> + return true;
> + }
Why not readTag which returns an enum for what type of tag it saw? In
any case, these functions are too similar to not be refactored.
> +
> + uint32_t readInt() {
> + uint32_t Result;
> + StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
> + assert (Str.empty() == false && "Unexpected memory buffer end!");
"assert (" --> "assert(".
> + Cursor += 4;
> + Result = *(uint32_t *)(Str.data());
> + return Result;
> + }
> +
> + uint64_t readInt64() {
> + uint64_t Lo = readInt();
> + uint64_t Hi = readInt();
> + uint64_t Result = Lo | (Hi << 32);
> + return Result;
> + }
> +
> + StringRef readString() {
> + uint32_t Len = readInt() * 4;
> + StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
> + Cursor += Len;
> + return Str;
> + }
> +
> + uint64_t getCursor() const { return Cursor; }
> +private:
> + MemoryBuffer *Buffer;
> + uint64_t Cursor;
> +};
> +
> +/// GCOVFile - Collects file information.
It collects *source* file information. One GCOVFile is the combination
of both the .gcno and the .gcda...
> +class GCOVFile {
> +public:
> + GCOVFile() : Format(InvalidGCOV) {}
> + ~GCOVFile();
> + bool read(GCOVBuffer &Buffer);
> + void dump();
> + void collectLineCounts(FileInfo &FI);
> +private:
> + enum GCOVFormat Format;
...but, it stores a single format even though read() is supposed to
take either/both the GCNO and GCDA. As far as I can tell, Format can
be hoisted into being a local variable inside read(), because that's
the only method that uses it.
> + SmallVector<GCOVFunction *, 16> Functions;
> +};
> +
> +/// GCOVFunction - Collects function information.
> +class GCOVFunction {
> +public:
> + GCOVFunction() : Ident(0), LineNumber(0) {}
> + ~GCOVFunction();
> + bool read(GCOVBuffer &Buffer, GCOVFormat Format);
> + void dump();
> + void collectLineCounts(FileInfo &FI);
> +private:
> + uint32_t Ident;
> + uint32_t LineNumber;
> + StringRef Name;
> + StringRef Filename;
> + SmallVector<GCOVBlock *, 16> Blocks;
> +};
> +
> +/// GCOVBlock - Collects block information.
> +class GCOVBlock {
> +public:
> + GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
> + ~GCOVBlock();
> + void addEdge(uint32_t N) { Edges.push_back(N); }
> + void addLine(StringRef Filename, uint32_t LineNo);
> + void addCount(uint64_t N) { Counter = N; }
> + void dump();
> + void collectLineCounts(FileInfo &FI);
> +private:
> + uint32_t Number;
> + uint64_t Counter;
> + SmallVector<uint32_t, 16> Edges;
> + StringMap<GCOVLines *> Lines;
> +};
> +
> +/// GCOVLines - A wrapper around a vector of int to keep track of line nos.
> +class GCOVLines {
> +public:
> + ~GCOVLines() { Lines.clear(); }
> + void add(uint32_t N) { Lines.push_back(N); }
> + void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
> + void dump();
> +
> +private:
> + SmallVector<uint32_t, 4> Lines;
> +};
> +
> +typedef SmallVector<uint32_t, 16> LineCounts;
> +class FileInfo {
> +public:
> + void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
> + void print();
> +private:
> + StringMap<LineCounts> LineInfo;
> +};
> +
> +
Extra newline.
> +}
> +
> +#endif
>
> Added: llvm/trunk/tools/llvm-cov/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/Makefile?rev=140712&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-cov/Makefile (added)
> +++ llvm/trunk/tools/llvm-cov/Makefile Wed Sep 28 13:50:00 2011
> @@ -0,0 +1,18 @@
> +##===- tools/llvm-gcov/Makefile ----------------------------*- Makefile -*-===##
"llvm-gcov" --> "llvm-cov" to match the directory it's in now.
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +
> +LEVEL = ../..
> +
> +TOOLNAME = llvm-cov
> +LINK_COMPONENTS := instrumentation
> +
> +# This tool has no plugins, optimize startup time.
> +TOOL_NO_EXPORTS = 1
> +
> +include $(LEVEL)/Makefile.common
>
> Added: llvm/trunk/tools/llvm-cov/llvm-cov.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/llvm-cov.cpp?rev=140712&view=auto
> ==============================================================================
> --- llvm/trunk/tools/llvm-cov/llvm-cov.cpp (added)
> +++ llvm/trunk/tools/llvm-cov/llvm-cov.cpp Wed Sep 28 13:50:00 2011
> @@ -0,0 +1,83 @@
> +//===- tools/llvm-cov/llvm-cov.cpp - LLVM coverage tool -------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +//
> +// llvm-cov is a command line tools to analyze and report coverage information.
> +//
> +//
Extra "//" line before and after.
> +//===----------------------------------------------------------------------===//
> +
> +#include "GCOVReader.h"
> +#include "llvm/ADT/OwningPtr.h"
> +#include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/ManagedStatic.h"
> +#include "llvm/Support/MemoryObject.h"
> +#include "llvm/Support/PrettyStackTrace.h"
> +#include "llvm/Support/Signals.h"
> +#include "llvm/Support/system_error.h"
> +using namespace llvm;
> +
> +static cl::opt<bool>
> +DumpGCOV("dump", cl::init(false), cl::desc("dump gcov file"));
> +
> +static cl::opt<std::string>
> +InputGCNO("gcno", cl::desc("<input gcno file>"), cl::init(""));
> +
> +static cl::opt<std::string>
> +InputGCDA("gcda", cl::desc("<input gcda file>"), cl::init(""));
> +
> +
> +//===----------------------------------------------------------------------===//
> +int main(int argc, char **argv) {
> + // Print a stack trace if we signal out.
> + sys::PrintStackTraceOnErrorSignal();
> + PrettyStackTraceProgram X(argc, argv);
> + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
> +
> + cl::ParseCommandLineOptions(argc, argv, "llvm cov\n");
> +
> +
Extra newline.
> + GCOVFile GF;
> + if (InputGCNO.empty())
> + errs() << " " << argv[0] << ": No gcov input file!\n";
> +
> + OwningPtr<MemoryBuffer> Buff;
> + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCNO, Buff)) {
> + errs() << InputGCNO << ": " << ec.message() << "\n";
> + return 1;
> + }
> + GCOVBuffer GB(Buff.take());
Would you mind naming Buff and GB in a way that indicates they're the
ones for GCNO? And similarly for Buff2 and GB2 being named related to
GCDA?
> +
> + if (!GF.read(GB)) {
> + errs() << "Invalid .gcno File!\n";
> + return 1;
> + }
> +
> + if (!InputGCDA.empty()) {
> + OwningPtr<MemoryBuffer> Buff2;
> + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputGCDA, Buff2)) {
> + errs() << InputGCDA << ": " << ec.message() << "\n";
> + return 1;
> + }
> + GCOVBuffer GB2(Buff2.take());
> +
> + if (!GF.read(GB2)) {
> + errs() << "Invalid .gcda File!\n";
> + return 1;
> + }
> + }
> +
> +
Extra newline.
> + if (DumpGCOV)
> + GF.dump();
> +
> + FileInfo FI;
> + GF.collectLineCounts(FI);
> + return 0;
> +}
More information about the llvm-commits
mailing list