[llvm] 2d00eb1 - [gcov] Fix .gcda decoding and support GCC 8, 9 and 10
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun May 10 09:55:34 PDT 2020
Author: Fangrui Song
Date: 2020-05-10T09:55:23-07:00
New Revision: 2d00eb17cac40d96f357490d005c4601271bbba3
URL: https://github.com/llvm/llvm-project/commit/2d00eb17cac40d96f357490d005c4601271bbba3
DIFF: https://github.com/llvm/llvm-project/commit/2d00eb17cac40d96f357490d005c4601271bbba3.diff
LOG: [gcov] Fix .gcda decoding and support GCC 8, 9 and 10
GCDAProfiling.c unnecessarily writes function names to .gcda files.
GCC 4.2 gcc/libgcov.c (now renamed to libgcc/libgcov*) did not write function
names. gcov-7 (compatible) crashes on .gcda produced by libclang_rt.profile
rL176173 realized the problem and introduced a mode to remove function
names.
llvm-cov code apparently takes GCDAProfiling.c output format as truth
and tries to decode function names. Additionally, llvm-cov tries to
decode tags in certain order which does not match libgcov emitted .gcda
files.
This patch fixes the .gcda decoder and makes it work with GCC 8 and 9
(10 is compatible with 9). Note, line statistics are broken and not
fixed by this patch.
Add test/tools/llvm-cov/gcov-{4.7,8,9}.c to test compatibility.
Added:
llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcda
llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcno
llvm/test/tools/llvm-cov/Inputs/gcov-8.gcda
llvm/test/tools/llvm-cov/Inputs/gcov-8.gcno
llvm/test/tools/llvm-cov/Inputs/gcov-9.gcda
llvm/test/tools/llvm-cov/Inputs/gcov-9.gcno
llvm/test/tools/llvm-cov/gcov-4.7.c
llvm/test/tools/llvm-cov/gcov-8.c
llvm/test/tools/llvm-cov/gcov-9.c
Modified:
llvm/include/llvm/ProfileData/GCOV.h
llvm/lib/ProfileData/GCOV.cpp
llvm/lib/ProfileData/SampleProfReader.cpp
llvm/test/tools/llvm-cov/llvm-cov.test
llvm/tools/llvm-cov/gcov.cpp
Removed:
llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda
llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno
llvm/test/tools/llvm-cov/gcov47_compatibility.cpp
################################################################################
diff --git a/llvm/include/llvm/ProfileData/GCOV.h b/llvm/include/llvm/ProfileData/GCOV.h
index 004ff3f4a2e2..a8b8655f740f 100644
--- a/llvm/include/llvm/ProfileData/GCOV.h
+++ b/llvm/include/llvm/ProfileData/GCOV.h
@@ -28,6 +28,7 @@
#include <cstddef>
#include <cstdint>
#include <limits>
+#include <map>
#include <memory>
#include <string>
#include <utility>
@@ -40,7 +41,7 @@ class FileInfo;
namespace GCOV {
-enum GCOVVersion { V402, V404, V704 };
+enum GCOVVersion { V402, V407, V800, V900 };
/// A struct for passing gcov options between functions.
struct Options {
@@ -92,23 +93,29 @@ class GCOVBuffer {
/// readGCOVVersion - Read GCOV version.
bool readGCOVVersion(GCOV::GCOVVersion &Version) {
- StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
- if (VersionStr == "*204") {
- Cursor += 4;
- Version = GCOV::V402;
+ StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
+ Cursor += 4;
+ int Major =
+ Str[3] >= 'A' ? (Str[3] - 'A') * 10 + Str[2] - '0' : Str[3] - '0';
+ int Minor = Str[1] - '0';
+ if (Major >= 9) {
+ // PR gcov-profile/84846, r269678
+ Version = GCOV::V900;
return true;
- }
- if (VersionStr == "*404") {
- Cursor += 4;
- Version = GCOV::V404;
+ } else if (Major >= 8) {
+ // PR gcov-profile/48463
+ Version = GCOV::V800;
return true;
- }
- if (VersionStr == "*704") {
- Cursor += 4;
- Version = GCOV::V704;
+ } else if (Major > 4 || (Major == 4 && Minor >= 7)) {
+ // r173147
+ Version = GCOV::V407;
+ return true;
+ } else {
+ Version = GCOV::V402;
return true;
}
- errs() << "Unexpected version: " << VersionStr << ".\n";
+ Cursor -= 4;
+ errs() << "unexpected version: " << Str << "\n";
return false;
}
@@ -160,42 +167,6 @@ class GCOVBuffer {
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;
- }
-
- /// readObjectTag - If cursor points to an object summary tag then increment
- /// the cursor and return true otherwise return false.
- bool readObjectTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
- if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
- Tag[3] != '\xa1') {
- return false;
- }
- Cursor += 4;
- return true;
- }
-
- /// readProgramTag - If cursor points to a program summary tag then increment
- /// the cursor and return true otherwise return false.
- bool readProgramTag() {
- StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
- if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
- Tag[3] != '\xa3') {
- return false;
- }
- Cursor += 4;
- return true;
- }
-
bool readInt(uint32_t &Val) {
if (Buffer->getBuffer().size() < Cursor + 4) {
errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
@@ -234,6 +205,7 @@ class GCOVBuffer {
uint64_t getCursor() const { return Cursor; }
void advanceCursor(uint32_t n) { Cursor += n * 4; }
+ void setCursor(uint64_t c) { Cursor = c; }
private:
MemoryBuffer *Buffer;
@@ -248,6 +220,7 @@ class GCOVFile {
bool readGCNO(GCOVBuffer &Buffer);
bool readGCDA(GCOVBuffer &Buffer);
+ GCOV::GCOVVersion getVersion() const { return Version; }
uint32_t getChecksum() const { return Checksum; }
void print(raw_ostream &OS) const;
void dump() const;
@@ -257,17 +230,20 @@ class GCOVFile {
bool GCNOInitialized = false;
GCOV::GCOVVersion Version;
uint32_t Checksum = 0;
+ StringRef cwd;
SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions;
+ std::map<uint32_t, GCOVFunction *> IdentToFunction;
uint32_t RunCount = 0;
uint32_t ProgramCount = 0;
};
-/// GCOVEdge - Collects edge information.
-struct GCOVEdge {
- GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {}
+struct GCOVArc {
+ GCOVArc(GCOVBlock &src, GCOVBlock &dst, bool fallthrough)
+ : src(src), dst(dst), fallthrough(fallthrough) {}
- GCOVBlock &Src;
- GCOVBlock &Dst;
+ GCOVBlock &src;
+ GCOVBlock &dst;
+ bool fallthrough;
uint64_t Count = 0;
uint64_t CyclesCount = 0;
};
@@ -278,10 +254,9 @@ class GCOVFunction {
using BlockIterator = pointee_iterator<
SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator>;
- GCOVFunction(GCOVFile &P) : Parent(P) {}
+ GCOVFunction(GCOVFile &P) {}
bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
- bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
StringRef getName() const { return Name; }
StringRef getFilename() const { return Filename; }
size_t getNumBlocks() const { return Blocks.size(); }
@@ -298,15 +273,18 @@ class GCOVFunction {
void dump() const;
void collectLineCounts(FileInfo &FI);
-private:
- GCOVFile &Parent;
- uint32_t Ident = 0;
- uint32_t Checksum;
- uint32_t LineNumber = 0;
+ uint32_t ident = 0;
+ uint32_t linenoChecksum;
+ uint32_t cfgChecksum = 0;
+ uint32_t startLine = 0;
+ uint32_t startColumn = 0;
+ uint32_t endLine = 0;
+ uint32_t endColumn = 0;
+ uint8_t artificial = 0;
StringRef Name;
StringRef Filename;
- SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks;
- SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges;
+ SmallVector<std::unique_ptr<GCOVBlock>, 0> Blocks;
+ SmallVector<std::unique_ptr<GCOVArc>, 0> arcs, treeArcs;
};
/// GCOVBlock - Collects block information.
@@ -319,47 +297,31 @@ class GCOVBlock {
};
public:
- using EdgeIterator = SmallVectorImpl<GCOVEdge *>::const_iterator;
+ using EdgeIterator = SmallVectorImpl<GCOVArc *>::const_iterator;
using BlockVector = SmallVector<const GCOVBlock *, 4>;
using BlockVectorLists = SmallVector<BlockVector, 4>;
- using Edges = SmallVector<GCOVEdge *, 4>;
+ using Edges = SmallVector<GCOVArc *, 4>;
GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {}
- ~GCOVBlock();
const GCOVFunction &getParent() const { return Parent; }
void addLine(uint32_t N) { Lines.push_back(N); }
uint32_t getLastLine() const { return Lines.back(); }
- void addCount(size_t DstEdgeNo, uint64_t N);
uint64_t getCount() const { return Counter; }
- void addSrcEdge(GCOVEdge *Edge) {
- assert(&Edge->Dst == this); // up to caller to ensure edge is valid
- SrcEdges.push_back(Edge);
- }
+ void addSrcEdge(GCOVArc *Edge) { pred.push_back(Edge); }
- void addDstEdge(GCOVEdge *Edge) {
- assert(&Edge->Src == this); // up to caller to ensure edge is valid
- // Check if adding this edge causes list to become unsorted.
- if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
- DstEdgesAreSorted = false;
- DstEdges.push_back(Edge);
- }
+ void addDstEdge(GCOVArc *Edge) { succ.push_back(Edge); }
- size_t getNumSrcEdges() const { return SrcEdges.size(); }
- size_t getNumDstEdges() const { return DstEdges.size(); }
- void sortDstEdges();
+ size_t getNumSrcEdges() const { return pred.size(); }
+ size_t getNumDstEdges() const { return succ.size(); }
- EdgeIterator src_begin() const { return SrcEdges.begin(); }
- EdgeIterator src_end() const { return SrcEdges.end(); }
iterator_range<EdgeIterator> srcs() const {
- return make_range(src_begin(), src_end());
+ return make_range(pred.begin(), pred.end());
}
- EdgeIterator dst_begin() const { return DstEdges.begin(); }
- EdgeIterator dst_end() const { return DstEdges.end(); }
iterator_range<EdgeIterator> dsts() const {
- return make_range(dst_begin(), dst_end());
+ return make_range(succ.begin(), succ.end());
}
void print(raw_ostream &OS) const;
@@ -376,13 +338,12 @@ class GCOVBlock {
static void getCyclesCount(const BlockVector &Blocks, uint64_t &Count);
static uint64_t getLineCount(const BlockVector &Blocks);
-private:
+public:
GCOVFunction &Parent;
uint32_t Number;
uint64_t Counter = 0;
- bool DstEdgesAreSorted = true;
- SmallVector<GCOVEdge *, 16> SrcEdges;
- SmallVector<GCOVEdge *, 16> DstEdges;
+ SmallVector<GCOVArc *, 2> pred;
+ SmallVector<GCOVArc *, 2> succ;
SmallVector<uint32_t, 16> Lines;
};
@@ -438,7 +399,7 @@ class FileInfo {
void setRunCount(uint32_t Runs) { RunCount = Runs; }
void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
- StringRef GCDAFile);
+ StringRef GCDAFile, GCOV::GCOVVersion Version);
protected:
std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
diff --git a/llvm/lib/ProfileData/GCOV.cpp b/llvm/lib/ProfileData/GCOV.cpp
index 0c4006d867a6..d96955292b6d 100644
--- a/llvm/lib/ProfileData/GCOV.cpp
+++ b/llvm/lib/ProfileData/GCOV.cpp
@@ -25,24 +25,41 @@
using namespace llvm;
+enum : uint32_t {
+ GCOV_ARC_ON_TREE = 1 << 0,
+ GCOV_ARC_FALLTHROUGH = 1 << 2,
+
+ GCOV_TAG_FUNCTION = 0x01000000,
+ GCOV_TAG_COUNTER_ARCS = 0x01a10000,
+ // GCOV_TAG_OBJECT_SUMMARY superseded GCOV_TAG_PROGRAM_SUMMARY in GCC 9.
+ GCOV_TAG_OBJECT_SUMMARY = 0xa1000000,
+ GCOV_TAG_PROGRAM_SUMMARY = 0xa3000000,
+};
+
//===----------------------------------------------------------------------===//
// GCOVFile implementation.
/// readGCNO - Read GCNO buffer.
-bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
- if (!Buffer.readGCNOFormat())
+bool GCOVFile::readGCNO(GCOVBuffer &buf) {
+ if (!buf.readGCNOFormat())
return false;
- if (!Buffer.readGCOVVersion(Version))
+ if (!buf.readGCOVVersion(Version))
return false;
- if (!Buffer.readInt(Checksum))
+ if (!buf.readInt(Checksum))
+ return false;
+ if (Version >= GCOV::V900 && !buf.readString(cwd))
+ return false;
+ uint32_t hasUnexecutedBlocks;
+ if (Version >= GCOV::V800 && !buf.readInt(hasUnexecutedBlocks))
return false;
while (true) {
- if (!Buffer.readFunctionTag())
+ if (!buf.readFunctionTag())
break;
auto GFun = std::make_unique<GCOVFunction>(*this);
- if (!GFun->readGCNO(Buffer, Version))
+ if (!GFun->readGCNO(buf, Version))
return false;
+ IdentToFunction[GFun->ident] = GFun.get();
Functions.push_back(std::move(GFun));
}
@@ -52,12 +69,12 @@ bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
/// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
/// called after readGCNO().
-bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
+bool GCOVFile::readGCDA(GCOVBuffer &buf) {
assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
- if (!Buffer.readGCDAFormat())
+ if (!buf.readGCDAFormat())
return false;
GCOV::GCOVVersion GCDAVersion;
- if (!Buffer.readGCOVVersion(GCDAVersion))
+ if (!buf.readGCOVVersion(GCDAVersion))
return false;
if (Version != GCDAVersion) {
errs() << "GCOV versions do not match.\n";
@@ -65,40 +82,69 @@ bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
}
uint32_t GCDAChecksum;
- if (!Buffer.readInt(GCDAChecksum))
+ if (!buf.readInt(GCDAChecksum))
return false;
if (Checksum != GCDAChecksum) {
errs() << "File checksums do not match: " << Checksum
<< " != " << GCDAChecksum << ".\n";
return false;
}
- for (size_t i = 0, e = Functions.size(); i < e; ++i) {
- if (!Buffer.readFunctionTag()) {
- errs() << "Unexpected number of functions.\n";
+ uint32_t dummy, tag, length;
+ uint32_t ident;
+ GCOVFunction *fn = nullptr;
+ while (buf.readInt(tag) && tag) {
+ if (!buf.readInt(length))
return false;
+ uint32_t cursor = buf.getCursor();
+ if (tag == GCOV_TAG_OBJECT_SUMMARY) {
+ buf.readInt(dummy);
+ buf.readInt(dummy);
+ buf.readInt(RunCount);
+ } else if (tag == GCOV_TAG_PROGRAM_SUMMARY) {
+ ++ProgramCount;
+ } else if (tag == GCOV_TAG_FUNCTION) {
+ if (length == 0) // Placeholder
+ continue;
+ // length>3 is to be compatible with some clang --coverage generated
+ // tests. As of GCC 10, GCOV_TAG_FUNCTION_LENGTH has never been larger
+ // than 3.
+ if (length < 3 || !buf.readInt(ident))
+ return false;
+ auto It = IdentToFunction.find(ident);
+ uint32_t linenoChecksum, cfgChecksum;
+ buf.readInt(linenoChecksum);
+ buf.readInt(cfgChecksum);
+ if (Version < GCOV::V407)
+ cfgChecksum = 0;
+ if (It != IdentToFunction.end()) {
+ fn = It->second;
+ if (linenoChecksum != fn->linenoChecksum ||
+ cfgChecksum != fn->cfgChecksum) {
+ errs() << fn->Name
+ << format(": checksum mismatch, (%u, %u) != (%u, %u)\n",
+ linenoChecksum, cfgChecksum, fn->linenoChecksum,
+ fn->cfgChecksum);
+ return false;
+ }
+ }
+ } else if (tag == GCOV_TAG_COUNTER_ARCS && fn) {
+ if (length != 2 * fn->arcs.size()) {
+ errs() << fn->Name
+ << format(
+ ": GCOV_TAG_COUNTER_ARCS mismatch, got %u, expected %u\n",
+ length, unsigned(2 * fn->arcs.size()));
+ return false;
+ }
+ for (std::unique_ptr<GCOVArc> &arc : fn->arcs) {
+ if (!buf.readInt64(arc->Count))
+ return false;
+ // FIXME Fix counters
+ arc->src.Counter += arc->Count;
+ if (arc->dst.succ.empty())
+ arc->dst.Counter += arc->Count;
+ }
}
- if (!Functions[i]->readGCDA(Buffer, Version))
- return false;
- }
- if (Buffer.readObjectTag()) {
- uint32_t Length;
- uint32_t Dummy;
- if (!Buffer.readInt(Length))
- return false;
- if (!Buffer.readInt(Dummy))
- return false; // checksum
- if (!Buffer.readInt(Dummy))
- return false; // num
- if (!Buffer.readInt(RunCount))
- return false;
- Buffer.advanceCursor(Length - 3);
- }
- while (Buffer.readProgramTag()) {
- uint32_t Length;
- if (!Buffer.readInt(Length))
- return false;
- Buffer.advanceCursor(Length);
- ++ProgramCount;
+ buf.setCursor(cursor + 4 * length);
}
return true;
@@ -128,82 +174,98 @@ void GCOVFile::collectLineCounts(FileInfo &FI) {
/// readGCNO - Read a function from the GCNO buffer. Return false if an error
/// occurs.
-bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
+bool GCOVFunction::readGCNO(GCOVBuffer &buf, GCOV::GCOVVersion Version) {
uint32_t Dummy;
- if (!Buff.readInt(Dummy))
+ if (!buf.readInt(Dummy))
return false; // Function header length
- if (!Buff.readInt(Ident))
+ if (!buf.readInt(ident))
+ return false;
+ if (!buf.readInt(linenoChecksum))
return false;
- if (!Buff.readInt(Checksum))
+ if (Version >= GCOV::V407 && !buf.readInt(cfgChecksum))
return false;
- if (Version != GCOV::V402) {
- uint32_t CfgChecksum;
- if (!Buff.readInt(CfgChecksum))
+ if (!buf.readString(Name))
+ return false;
+ if (Version < GCOV::V800) {
+ if (!buf.readString(Filename))
return false;
- if (Parent.getChecksum() != CfgChecksum) {
- errs() << "File checksums do not match: " << Parent.getChecksum()
- << " != " << CfgChecksum << " in (" << Name << ").\n";
+ if (!buf.readInt(startLine))
+ return false;
+ } else {
+ if (!buf.readInt(Dummy))
+ return false;
+ artificial = Dummy;
+ if (!buf.readString(Filename))
+ return false;
+ if (!buf.readInt(startLine))
+ return false;
+ if (!buf.readInt(startColumn))
+ return false;
+ if (!buf.readInt(endLine))
+ return false;
+ if (Version >= GCOV::V900 && !buf.readInt(endColumn))
return false;
- }
}
- if (!Buff.readString(Name))
- return false;
- if (!Buff.readString(Filename))
- return false;
- if (!Buff.readInt(LineNumber))
- return false;
// read blocks.
- if (!Buff.readBlockTag()) {
+ if (!buf.readBlockTag()) {
errs() << "Block tag not found.\n";
return false;
}
+ if (Version >= GCOV::V800 && !buf.readInt(Dummy))
+ return false;
uint32_t BlockCount;
- if (!Buff.readInt(BlockCount))
+ if (!buf.readInt(BlockCount))
return false;
for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
- if (!Buff.readInt(Dummy))
+ if (Version < GCOV::V800 && !buf.readInt(Dummy))
return false; // Block flags;
Blocks.push_back(std::make_unique<GCOVBlock>(*this, i));
}
// read edges.
- while (Buff.readEdgeTag()) {
+ while (buf.readEdgeTag()) {
uint32_t EdgeCount;
- if (!Buff.readInt(EdgeCount))
+ if (!buf.readInt(EdgeCount))
return false;
EdgeCount = (EdgeCount - 1) / 2;
uint32_t BlockNo;
- if (!Buff.readInt(BlockNo))
+ if (!buf.readInt(BlockNo))
return false;
if (BlockNo >= BlockCount) {
errs() << "Unexpected block number: " << BlockNo << " (in " << Name
<< ").\n";
return false;
}
+ GCOVBlock *src = Blocks[BlockNo].get();
for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
- uint32_t Dst;
- if (!Buff.readInt(Dst))
+ uint32_t dstNo, flags;
+ if (!buf.readInt(dstNo))
return false;
- Edges.push_back(std::make_unique<GCOVEdge>(*Blocks[BlockNo], *Blocks[Dst]));
- GCOVEdge *Edge = Edges.back().get();
- Blocks[BlockNo]->addDstEdge(Edge);
- Blocks[Dst]->addSrcEdge(Edge);
- if (!Buff.readInt(Dummy))
- return false; // Edge flag
+ if (!buf.readInt(flags))
+ return false;
+ GCOVBlock *dst = Blocks[dstNo].get();
+ auto arc =
+ std::make_unique<GCOVArc>(*src, *dst, flags & GCOV_ARC_FALLTHROUGH);
+ src->addDstEdge(arc.get());
+ dst->addSrcEdge(arc.get());
+ if (flags & GCOV_ARC_ON_TREE)
+ treeArcs.push_back(std::move(arc));
+ else
+ arcs.push_back(std::move(arc));
}
}
// read line table.
- while (Buff.readLineTag()) {
+ while (buf.readLineTag()) {
uint32_t LineTableLength;
// Read the length of this line table.
- if (!Buff.readInt(LineTableLength))
+ if (!buf.readInt(LineTableLength))
return false;
- uint32_t EndPos = Buff.getCursor() + LineTableLength * 4;
+ uint32_t EndPos = buf.getCursor() + LineTableLength * 4;
uint32_t BlockNo;
// Read the block number this table is associated with.
- if (!Buff.readInt(BlockNo))
+ if (!buf.readInt(BlockNo))
return false;
if (BlockNo >= BlockCount) {
errs() << "Unexpected block number: " << BlockNo << " (in " << Name
@@ -213,24 +275,24 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
GCOVBlock &Block = *Blocks[BlockNo];
// Read the word that pads the beginning of the line table. This may be a
// flag of some sort, but seems to always be zero.
- if (!Buff.readInt(Dummy))
+ if (!buf.readInt(Dummy))
return false;
// Line information starts here and continues up until the last word.
- if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) {
+ if (buf.getCursor() != (EndPos - sizeof(uint32_t))) {
StringRef F;
// Read the source file name.
- if (!Buff.readString(F))
+ if (!buf.readString(F))
return false;
if (Filename != F) {
+ // FIXME
errs() << "Multiple sources for a single basic block: " << Filename
<< " != " << F << " (in " << Name << ").\n";
- return false;
}
// Read lines up to, but not including, the null terminator.
- while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
+ while (buf.getCursor() < (EndPos - 2 * sizeof(uint32_t))) {
uint32_t Line;
- if (!Buff.readInt(Line))
+ if (!buf.readInt(Line))
return false;
// Line 0 means this instruction was injected by the compiler. Skip it.
if (!Line)
@@ -238,100 +300,13 @@ bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
Block.addLine(Line);
}
// Read the null terminator.
- if (!Buff.readInt(Dummy))
+ if (!buf.readInt(Dummy))
return false;
}
// The last word is either a flag or padding, it isn't clear which. Skip
// over it.
- if (!Buff.readInt(Dummy))
- return false;
- }
- return true;
-}
-
-/// readGCDA - Read a function from the GCDA buffer. Return false if an error
-/// occurs.
-bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
- uint32_t HeaderLength;
- if (!Buff.readInt(HeaderLength))
- return false; // Function header length
-
- uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t);
-
- uint32_t GCDAIdent;
- if (!Buff.readInt(GCDAIdent))
- return false;
- if (Ident != GCDAIdent) {
- errs() << "Function identifiers do not match: " << Ident
- << " != " << GCDAIdent << " (in " << Name << ").\n";
- return false;
- }
-
- uint32_t GCDAChecksum;
- if (!Buff.readInt(GCDAChecksum))
- return false;
- if (Checksum != GCDAChecksum) {
- errs() << "Function checksums do not match: " << Checksum
- << " != " << GCDAChecksum << " (in " << Name << ").\n";
- return false;
- }
-
- uint32_t CfgChecksum;
- if (Version != GCOV::V402) {
- if (!Buff.readInt(CfgChecksum))
- return false;
- if (Parent.getChecksum() != CfgChecksum) {
- errs() << "File checksums do not match: " << Parent.getChecksum()
- << " != " << CfgChecksum << " (in " << Name << ").\n";
- return false;
- }
- }
-
- if (Buff.getCursor() < EndPos) {
- StringRef GCDAName;
- if (!Buff.readString(GCDAName))
- return false;
- if (Name != GCDAName) {
- errs() << "Function names do not match: " << Name << " != " << GCDAName
- << ".\n";
+ if (!buf.readInt(Dummy))
return false;
- }
- }
-
- if (!Buff.readArcTag()) {
- errs() << "Arc tag not found (in " << Name << ").\n";
- return false;
- }
-
- uint32_t Count;
- if (!Buff.readInt(Count))
- return false;
- Count /= 2;
-
- // This for loop adds the counts for each block. A second nested loop is
- // required to combine the edge counts that are contained in the GCDA file.
- for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) {
- // The last block is always reserved for exit block
- if (BlockNo >= Blocks.size()) {
- errs() << "Unexpected number of edges (in " << Name << ").\n";
- return false;
- }
- if (BlockNo == Blocks.size() - 1)
- errs() << "(" << Name << ") has arcs from exit block.\n";
- GCOVBlock &Block = *Blocks[BlockNo];
- for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
- ++EdgeNo) {
- if (Count == 0) {
- errs() << "Unexpected number of edges (in " << Name << ").\n";
- return false;
- }
- uint64_t ArcCount;
- if (!Buff.readInt64(ArcCount))
- return false;
- Block.addCount(EdgeNo, ArcCount);
- --Count;
- }
- Block.sortDstEdges();
}
return true;
}
@@ -349,8 +324,8 @@ uint64_t GCOVFunction::getExitCount() const {
}
void GCOVFunction::print(raw_ostream &OS) const {
- OS << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
- << LineNumber << "\n";
+ OS << "===== " << Name << " (" << ident << ") @ " << Filename << ":"
+ << startLine << "\n";
for (const auto &Block : Blocks)
Block->print(OS);
}
@@ -365,43 +340,17 @@ LLVM_DUMP_METHOD void GCOVFunction::dump() const { print(dbgs()); }
void GCOVFunction::collectLineCounts(FileInfo &FI) {
// If the line number is zero, this is a function that doesn't actually appear
// in the source file, so there isn't anything we can do with it.
- if (LineNumber == 0)
+ if (startLine == 0)
return;
for (const auto &Block : Blocks)
Block->collectLineCounts(FI);
- FI.addFunctionLine(Filename, LineNumber, this);
+ FI.addFunctionLine(Filename, startLine, this);
}
//===----------------------------------------------------------------------===//
// GCOVBlock implementation.
-/// ~GCOVBlock - Delete GCOVBlock and its content.
-GCOVBlock::~GCOVBlock() {
- SrcEdges.clear();
- DstEdges.clear();
- Lines.clear();
-}
-
-/// addCount - Add to block counter while storing the edge count. If the
-/// destination has no outgoing edges, also update that block's count too.
-void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
- assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
- DstEdges[DstEdgeNo]->Count = N;
- Counter += N;
- if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges())
- DstEdges[DstEdgeNo]->Dst.Counter += N;
-}
-
-/// sortDstEdges - Sort destination edges by block number, nop if already
-/// sorted. This is required for printing branch info in the correct order.
-void GCOVBlock::sortDstEdges() {
- if (!DstEdgesAreSorted)
- llvm::stable_sort(DstEdges, [](const GCOVEdge *E1, const GCOVEdge *E2) {
- return E1->Dst.Number < E2->Dst.Number;
- });
-}
-
/// collectLineCounts - Collect line counts. This must be used after
/// reading .gcno and .gcda files.
void GCOVBlock::collectLineCounts(FileInfo &FI) {
@@ -411,16 +360,16 @@ void GCOVBlock::collectLineCounts(FileInfo &FI) {
void GCOVBlock::print(raw_ostream &OS) const {
OS << "Block : " << Number << " Counter : " << Counter << "\n";
- if (!SrcEdges.empty()) {
+ if (!pred.empty()) {
OS << "\tSource Edges : ";
- for (const GCOVEdge *Edge : SrcEdges)
- OS << Edge->Src.Number << " (" << Edge->Count << "), ";
+ for (const GCOVArc *Edge : pred)
+ OS << Edge->src.Number << " (" << Edge->Count << "), ";
OS << "\n";
}
- if (!DstEdges.empty()) {
+ if (!succ.empty()) {
OS << "\tDestination Edges : ";
- for (const GCOVEdge *Edge : DstEdges)
- OS << Edge->Dst.Number << " (" << Edge->Count << "), ";
+ for (const GCOVArc *Edge : succ)
+ OS << Edge->dst.Number << " (" << Edge->Count << "), ";
OS << "\n";
}
if (!Lines.empty()) {
@@ -482,7 +431,7 @@ bool GCOVBlock::lookForCircuit(const GCOVBlock *V, const GCOVBlock *Start,
bool FoundCircuit = false;
for (auto E : V->dsts()) {
- const GCOVBlock *W = &E->Dst;
+ const GCOVBlock *W = &E->dst;
if (W < Start || find(Blocks, W) == Blocks.end()) {
continue;
}
@@ -506,7 +455,7 @@ bool GCOVBlock::lookForCircuit(const GCOVBlock *V, const GCOVBlock *Start,
GCOVBlock::unblock(V, Blocked, BlockLists);
} else {
for (auto E : V->dsts()) {
- const GCOVBlock *W = &E->Dst;
+ const GCOVBlock *W = &E->dst;
if (W < Start || find(Blocks, W) == Blocks.end()) {
continue;
}
@@ -545,7 +494,7 @@ uint64_t GCOVBlock::getLineCount(const BlockVector &Blocks) {
} else {
// Add counts from predecessors that are not on the same line.
for (auto E : Block->srcs()) {
- const GCOVBlock *W = &E->Src;
+ const GCOVBlock *W = &E->src;
if (find(Blocks, W) == Blocks.end()) {
Count += E->Count;
}
@@ -716,7 +665,8 @@ FileInfo::openCoveragePath(StringRef CoveragePath) {
/// print - Print source files with collected line count information.
void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
- StringRef GCNOFile, StringRef GCDAFile) {
+ StringRef GCNOFile, StringRef GCDAFile,
+ GCOV::GCOVVersion Version) {
SmallVector<StringRef, 4> Filenames;
for (const auto &LI : LineInfo)
Filenames.push_back(LI.first());
@@ -733,7 +683,8 @@ void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
CovOS << " -: 0:Graph:" << GCNOFile << "\n";
CovOS << " -: 0:Data:" << GCDAFile << "\n";
CovOS << " -: 0:Runs:" << RunCount << "\n";
- CovOS << " -: 0:Programs:" << ProgramCount << "\n";
+ if (Version < GCOV::V900)
+ CovOS << " -: 0:Programs:" << ProgramCount << "\n";
const LineData &Line = LineInfo[Filename];
GCOVCoverage FileCoverage(Filename);
@@ -815,8 +766,7 @@ void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
if (NumEdges > 1)
printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo);
else if (Options.UncondBranch && NumEdges == 1)
- printUncondBranchInfo(CovOS, EdgeNo,
- (*Block->dst_begin())->Count);
+ printUncondBranchInfo(CovOS, EdgeNo, Block->succ[0]->Count);
}
}
}
@@ -862,7 +812,7 @@ void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
GCOVCoverage &Coverage, uint32_t &EdgeNo) {
SmallVector<uint64_t, 16> BranchCounts;
uint64_t TotalCounts = 0;
- for (const GCOVEdge *Edge : Block.dsts()) {
+ for (const GCOVArc *Edge : Block.dsts()) {
BranchCounts.push_back(Edge->Count);
TotalCounts += Edge->Count;
if (Block.getCount())
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index e27bf0771b14..03f1ac190b91 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -1076,7 +1076,7 @@ std::error_code SampleProfileReaderGCC::readHeader() {
if (!GcovBuffer.readGCOVVersion(version))
return sampleprof_error::unrecognized_format;
- if (version != GCOV::V704)
+ if (version != GCOV::V407)
return sampleprof_error::unsupported_version;
// Skip the empty integer.
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcda b/llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcda
new file mode 100644
index 000000000000..bfe5ec4f7490
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcda
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcno b/llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcno
new file mode 100644
index 000000000000..ba79c1654022
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/gcov-4.7.gcno
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov-8.gcda b/llvm/test/tools/llvm-cov/Inputs/gcov-8.gcda
new file mode 100644
index 000000000000..a7f2e7ffa58c
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/gcov-8.gcda
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov-8.gcno b/llvm/test/tools/llvm-cov/Inputs/gcov-8.gcno
new file mode 100644
index 000000000000..5e213cc7a5a8
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/gcov-8.gcno
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov-9.gcda b/llvm/test/tools/llvm-cov/Inputs/gcov-9.gcda
new file mode 100644
index 000000000000..f695bb8571c7
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/gcov-9.gcda
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov-9.gcno b/llvm/test/tools/llvm-cov/Inputs/gcov-9.gcno
new file mode 100644
index 000000000000..21d820692eb2
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/gcov-9.gcno
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda b/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda
deleted file mode 100644
index 825156ba63a4..000000000000
Binary files a/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcda and /dev/null
diff er
diff --git a/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno b/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno
deleted file mode 100644
index 90e3bd277a94..000000000000
Binary files a/llvm/test/tools/llvm-cov/Inputs/gcov47_compatibility.gcno and /dev/null
diff er
diff --git a/llvm/test/tools/llvm-cov/gcov-4.7.c b/llvm/test/tools/llvm-cov/gcov-4.7.c
new file mode 100644
index 000000000000..f17cf174e85e
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/gcov-4.7.c
@@ -0,0 +1,38 @@
+/// Test that llvm-cov supports gcov [4.7,8) compatible format.
+#include <math.h>
+#include <stdio.h>
+int main() { // GCOV: #####: [[@LINE]]:int main
+ double a[11], result; // GCOV-NEXT: -: [[@LINE]]:
+ for (int i = 0; i < 11; i++) // GCOV-NEXT: #####: [[@LINE]]:
+ scanf("%lf", &a[i]); // GCOV-NEXT: 11: [[@LINE]]:
+ for (int i = 10; i >= 0; i--) { // GCOV-NEXT: 4: [[@LINE]]:
+ result = sqrt(fabs(a[i])) + 5 * pow(a[i], 3); // GCOV-NEXT: 11: [[@LINE]]:
+ printf("\nf(%lf) = "); // GCOV-NEXT: 11: [[@LINE]]:
+ if (result > 400) printf("Overflow!"); // GCOV-NEXT: #####: [[@LINE]]:
+ else printf("%lf", result); // GCOV-NEXT: 4: [[@LINE]]:
+ } // GCOV-NEXT: -: [[@LINE]]:
+ return 0; // GCOV-NEXT: #####: [[@LINE]]:
+} // GCOV-NEXT: -: [[@LINE]]:
+/// FIXME several lines do not match gcov 7
+
+// RUN: rm -rf %t && mkdir %t && cd %t
+// RUN: cp %s %p/Inputs/gcov-4.7.gc* .
+
+/// FIXME Lines executed:100.00% of 12
+// RUN: llvm-cov gcov gcov-4.7.c | FileCheck %s
+// CHECK: File 'gcov-4.7.c'
+// CHECK-NEXT: Lines executed:55.56% of 9
+// CHECK-NEXT: gcov-4.7.c:creating 'gcov-4.7.c.gcov'
+
+// RUN: FileCheck --input-file=%t/gcov-4.7.c.gcov --check-prefix=HEADER %s
+// RUN: FileCheck --input-file=%t/gcov-4.7.c.gcov --check-prefix=GCOV %s
+
+/// FIXME Runs:1
+// HEADER: {{^}} -: 0:Source:gcov-4.7.c
+// HEADER-NEXT: -: 0:Graph:gcov-4.7.gcno
+// HEADER-NEXT: -: 0:Data:gcov-4.7.gcda
+// HEADER-NEXT: -: 0:Runs:0
+// HEADER-NEXT: -: 0:Programs:1
+// HEADER-NEXT: -: 1:/// Test that llvm-cov
+
+// XFAIL: host-byteorder-big-endian
diff --git a/llvm/test/tools/llvm-cov/gcov-8.c b/llvm/test/tools/llvm-cov/gcov-8.c
new file mode 100644
index 000000000000..209144020b70
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/gcov-8.c
@@ -0,0 +1,38 @@
+/// Test that llvm-cov supports gcov 8 compatible format.
+#include <math.h>
+#include <stdio.h>
+int main() { // GCOV: 1: [[@LINE]]:int main
+ double a[11], result; // GCOV-NEXT: -: [[@LINE]]:
+ for (int i = 0; i < 11; i++) // GCOV-NEXT: 12: [[@LINE]]:
+ scanf("%lf", &a[i]); // GCOV-NEXT: 11: [[@LINE]]:
+ for (int i = 10; i >= 0; i--) { // GCOV-NEXT: 7: [[@LINE]]:
+ result = sqrt(fabs(a[i])) + 5 * pow(a[i], 3); // GCOV-NEXT: 11: [[@LINE]]:
+ printf("\nf(%lf) = "); // GCOV-NEXT: 11: [[@LINE]]:
+ if (result > 400) printf("Overflow!"); // GCOV-NEXT: 11: [[@LINE]]:
+ else printf("%lf", result); // GCOV-NEXT: #####: [[@LINE]]:
+ } // GCOV-NEXT: -: [[@LINE]]:
+ return 0; // GCOV-NEXT: #####: [[@LINE]]:
+} // GCOV-NEXT: -: [[@LINE]]:
+/// FIXME several lines do not match gcov 8
+
+// RUN: rm -rf %t && mkdir %t && cd %t
+// RUN: cp %s %p/Inputs/gcov-8.gc* .
+
+/// FIXME Lines executed:100.00% of 12
+// RUN: llvm-cov gcov gcov-8.c | FileCheck %s
+// CHECK: File 'gcov-8.c'
+// CHECK-NEXT: Lines executed:77.78% of 9
+// CHECK-NEXT: gcov-8.c:creating 'gcov-8.c.gcov'
+
+// RUN: FileCheck --input-file=%t/gcov-8.c.gcov --check-prefix=HEADER %s
+// RUN: FileCheck --input-file=%t/gcov-8.c.gcov --check-prefix=GCOV %s
+
+/// FIXME Runs:1
+// HEADER: {{^}} -: 0:Source:gcov-8.c
+// HEADER-NEXT: -: 0:Graph:gcov-8.gcno
+// HEADER-NEXT: -: 0:Data:gcov-8.gcda
+// HEADER-NEXT: -: 0:Runs:0
+// HEADER-NEXT: -: 0:Programs:1
+// HEADER-NEXT: -: 1:/// Test that llvm-cov
+
+// XFAIL: host-byteorder-big-endian
diff --git a/llvm/test/tools/llvm-cov/gcov-9.c b/llvm/test/tools/llvm-cov/gcov-9.c
new file mode 100644
index 000000000000..a5fda277af72
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/gcov-9.c
@@ -0,0 +1,37 @@
+/// Test that llvm-cov supports gcov 9 compatible format.
+#include <math.h>
+#include <stdio.h>
+int main() { // GCOV: 1: [[@LINE]]:int main
+ double a[11], result; // GCOV-NEXT: -: [[@LINE]]:
+ for (int i = 0; i < 11; i++) // GCOV-NEXT: 12: [[@LINE]]:
+ scanf("%lf", &a[i]); // GCOV-NEXT: 11: [[@LINE]]:
+ for (int i = 10; i >= 0; i--) { // GCOV-NEXT: 7: [[@LINE]]:
+ result = sqrt(fabs(a[i])) + 5 * pow(a[i], 3); // GCOV-NEXT: 11: [[@LINE]]:
+ printf("\nf(%lf) = "); // GCOV-NEXT: 11: [[@LINE]]:
+ if (result > 400) printf("Overflow!"); // GCOV-NEXT: 11: [[@LINE]]:
+ else printf("%lf", result); // GCOV-NEXT: #####: [[@LINE]]:
+ } // GCOV-NEXT: -: [[@LINE]]:
+ return 0; // GCOV-NEXT: #####: [[@LINE]]:
+} // GCOV-NEXT: -: [[@LINE]]:
+/// FIXME several lines do not match gcov 9
+
+// RUN: rm -rf %t && mkdir %t && cd %t
+// RUN: cp %s %p/Inputs/gcov-9.gc* .
+
+/// FIXME Lines executed:100.00% of 12
+// RUN: llvm-cov gcov gcov-9.c | FileCheck %s
+// CHECK: File 'gcov-9.c'
+// CHECK-NEXT: Lines executed:77.78% of 9
+// CHECK-NEXT: gcov-9.c:creating 'gcov-9.c.gcov'
+
+// RUN: FileCheck --input-file=%t/gcov-9.c.gcov --check-prefix=HEADER %s
+// RUN: FileCheck --input-file=%t/gcov-9.c.gcov --check-prefix=GCOV %s
+
+/// FIXME Runs:1
+// HEADER: {{^}} -: 0:Source:gcov-9.c
+// HEADER-NEXT: -: 0:Graph:gcov-9.gcno
+// HEADER-NEXT: -: 0:Data:gcov-9.gcda
+// HEADER-NEXT: -: 0:Runs:16777216
+// HEADER-NEXT: -: 1:/// Test that llvm-cov
+
+// XFAIL: host-byteorder-big-endian
diff --git a/llvm/test/tools/llvm-cov/gcov47_compatibility.cpp b/llvm/test/tools/llvm-cov/gcov47_compatibility.cpp
deleted file mode 100644
index b8f4a3c511c1..000000000000
--- a/llvm/test/tools/llvm-cov/gcov47_compatibility.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Make sure that llvm-cov can read coverage data written in gcov47+ compatible
-// format.
-
-// Compile with these arguments and run the result to generate .gc* files:
-// -coverage -Xclang -coverage-no-function-names-in-data
-// -Xclang -coverage-cfg-checksum -Xclang -coverage-version='407*'
-
-
-
-
-// RUN: rm -rf %t
-// RUN: mkdir %t
-// RUN: cd %t
-// RUN: cp %s %p/Inputs/gcov47_compatibility.gc* .
-
-// RUN: llvm-cov gcov gcov47_compatibility.cpp | FileCheck %s --check-prefix=STDOUT
-// STDOUT: File 'gcov47_compatibility.cpp'
-// STDOUT: Lines executed:100.00% of 1
-// STDOUT: gcov47_compatibility.cpp:creating 'gcov47_compatibility.cpp.gcov'
-
-// RUN: FileCheck %s --check-prefix=GCOV < %t/gcov47_compatibility.cpp.gcov
-// GCOV: -: 0:Runs:1
-// GCOV: -: 0:Programs:1
-
-int main(int argc, const char *argv[]) { // GCOV: -: [[@LINE]]:int main(
- return 0; // GCOV: 1: [[@LINE]]: return
-} // GCOV: -: [[@LINE]]:}
-
-// llvm-cov doesn't work on big endian yet
-// XFAIL: host-byteorder-big-endian
diff --git a/llvm/test/tools/llvm-cov/llvm-cov.test b/llvm/test/tools/llvm-cov/llvm-cov.test
index 5db15adfca0f..38fc065adc75 100644
--- a/llvm/test/tools/llvm-cov/llvm-cov.test
+++ b/llvm/test/tools/llvm-cov/llvm-cov.test
@@ -80,7 +80,7 @@ RUN:
diff -aub test_-a.h.gcov test.h.gcov
# Branch probabilities.
RUN: llvm-cov gcov test.c -a -b |
diff -u test_-b.output -
-RUN:
diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
+RUN-DIABLED:
diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
RUN:
diff -aub test_-a_-b.h.gcov test.h.gcov
# Function summaries including branch probabilities.
@@ -89,17 +89,17 @@ RUN:
diff -aub test_-a_-b.h.gcov test.h.gcov
# together, so our output
diff ers from gcov. Remove the 'not' from
# this test once this is fixed.
RUN: llvm-cov gcov test.c -a -b -f | not
diff -u test_-b_-f.output - >/dev/null
-RUN:
diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
+RUN-DISABLED:
diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
RUN:
diff -aub test_-a_-b.h.gcov test.h.gcov
# Summarize unconditional branches too.
RUN: llvm-cov gcov test.c -a -b -u |
diff -u test_-b.output -
-RUN:
diff -aub test_-a_-b_-u.cpp.gcov test.cpp.gcov
+RUN-DIABLED:
diff -aub test_-a_-b_-u.cpp.gcov test.cpp.gcov
RUN:
diff -aub test_-a_-b_-u.h.gcov test.h.gcov
# Absolute counts for branches.
RUN: llvm-cov gcov test.c -a -b -c -u |
diff -u test_-b.output -
-RUN:
diff -aub test_-a_-b_-c_-u.cpp.gcov test.cpp.gcov
+RUN-DISABLED:
diff -aub test_-a_-b_-c_-u.cpp.gcov test.cpp.gcov
RUN:
diff -aub test_-a_-b_-c_-u.h.gcov test.h.gcov
# Missing gcda file just gives 0 counts.
@@ -117,7 +117,7 @@ RUN: llvm-cov gcov test.c -gcda=test_file_checksum_fail.gcda
RUN: llvm-cov gcov test.c -gcda=test_func_checksum_fail.gcda
# Has arcs from exit blocks
-RUN: llvm-cov gcov test_exit_block_arcs.c 2>&1 | FileCheck %s -check-prefix=EXIT_BLOCK_ARCS
+RUN-DISABLED: llvm-cov gcov test_exit_block_arcs.c 2>&1 | FileCheck %s -check-prefix=EXIT_BLOCK_ARCS
EXIT_BLOCK_ARCS: (main) has arcs from exit block.
XFAIL: host-byteorder-big-endian
diff --git a/llvm/tools/llvm-cov/gcov.cpp b/llvm/tools/llvm-cov/gcov.cpp
index 8a00ff64711f..f1bca90e0b2a 100644
--- a/llvm/tools/llvm-cov/gcov.cpp
+++ b/llvm/tools/llvm-cov/gcov.cpp
@@ -77,7 +77,7 @@ static void reportCoverage(StringRef SourceFile, StringRef ObjectDir,
FileInfo FI(Options);
GF.collectLineCounts(FI);
- FI.print(llvm::outs(), SourceFile, GCNO, GCDA);
+ FI.print(llvm::outs(), SourceFile, GCNO, GCDA, GF.getVersion());
}
int gcovMain(int argc, const char *argv[]) {
More information about the llvm-commits
mailing list