Navigation Menu

Skip to content

Commit

Permalink
[gcov] Refactor llvm-cov gcov and add SourceInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
MaskRay committed Jun 16, 2020
1 parent 28ebdf1 commit 4cd7ba7
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 51 deletions.
56 changes: 37 additions & 19 deletions llvm/include/llvm/ProfileData/GCOV.h
Expand Up @@ -192,6 +192,9 @@ class GCOVFile {
void dump() const;
void collectLineCounts(FileInfo &FI);

std::vector<std::string> filenames;
StringMap<unsigned> filenameToIdx;

private:
bool GCNOInitialized = false;
GCOV::GCOVVersion Version;
Expand All @@ -201,6 +204,11 @@ class GCOVFile {
std::map<uint32_t, GCOVFunction *> IdentToFunction;
uint32_t RunCount = 0;
uint32_t ProgramCount = 0;

using iterator = pointee_iterator<
SmallVectorImpl<std::unique_ptr<GCOVFunction>>::const_iterator>;
iterator begin() const { return iterator(Functions.begin()); }
iterator end() const { return iterator(Functions.end()); }
};

struct GCOVArc {
Expand All @@ -220,10 +228,10 @@ class GCOVFunction {
using BlockIterator = pointee_iterator<
SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator>;

GCOVFunction(GCOVFile &P) {}
GCOVFunction(GCOVFile &file) : file(file) {}

StringRef getName() const { return Name; }
StringRef getFilename() const { return Filename; }
StringRef getFilename() const;
size_t getNumBlocks() const { return Blocks.size(); }
uint64_t getEntryCount() const;
uint64_t getExitCount() const;
Expand All @@ -238,6 +246,7 @@ class GCOVFunction {
void dump() const;
void collectLineCounts(FileInfo &FI);

GCOVFile &file;
uint32_t ident = 0;
uint32_t linenoChecksum;
uint32_t cfgChecksum = 0;
Expand All @@ -247,7 +256,7 @@ class GCOVFunction {
uint32_t endColumn = 0;
uint8_t artificial = 0;
StringRef Name;
StringRef Filename;
unsigned srcIdx;
SmallVector<std::unique_ptr<GCOVBlock>, 0> Blocks;
SmallVector<std::unique_ptr<GCOVArc>, 0> arcs, treeArcs;
};
Expand Down Expand Up @@ -312,6 +321,28 @@ class GCOVBlock {
SmallVector<uint32_t, 16> Lines;
};

struct GCOVCoverage {
GCOVCoverage() = default;
GCOVCoverage(StringRef Name) : Name(Name) {}

StringRef Name;

uint32_t LogicalLines = 0;
uint32_t LinesExec = 0;

uint32_t Branches = 0;
uint32_t BranchesExec = 0;
uint32_t BranchesTaken = 0;
};

struct SourceInfo {
StringRef filename;
std::string name;
std::vector<GCOVFunction *> functions;
GCOVCoverage coverage;
SourceInfo(StringRef filename) : filename(filename) {}
};

class FileInfo {
protected:
// It is unlikely--but possible--for multiple functions to be on the same
Expand All @@ -332,20 +363,8 @@ class FileInfo {
uint32_t LastLine = 0;
};

struct GCOVCoverage {
GCOVCoverage(StringRef Name) : Name(Name) {}

StringRef Name;

uint32_t LogicalLines = 0;
uint32_t LinesExec = 0;

uint32_t Branches = 0;
uint32_t BranchesExec = 0;
uint32_t BranchesTaken = 0;
};

public:
friend class GCOVFile;
FileInfo(const GCOV::Options &Options) : Options(Options) {}

void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
Expand All @@ -364,7 +383,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, GCOV::GCOVVersion Version);
StringRef GCDAFile, GCOVFile &file);

protected:
std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
Expand All @@ -386,11 +405,10 @@ class FileInfo {
uint32_t RunCount = 0;
uint32_t ProgramCount = 0;

using FileCoverageList = SmallVector<std::pair<std::string, GCOVCoverage>, 4>;
using FuncCoverageMap = MapVector<const GCOVFunction *, GCOVCoverage>;

FileCoverageList FileCoverages;
FuncCoverageMap FuncCoverages;
std::vector<SourceInfo> sources;
};

} // end namespace llvm
Expand Down
50 changes: 31 additions & 19 deletions llvm/lib/ProfileData/GCOV.cpp
Expand Up @@ -68,18 +68,23 @@ bool GCOVFile::readGCNO(GCOVBuffer &buf) {
if (Version >= GCOV::V407)
fn->cfgChecksum = buf.getWord();
buf.readString(fn->Name);
StringRef filename;
if (Version < GCOV::V800) {
buf.readString(fn->Filename);
filename = buf.getString();
fn->startLine = buf.getWord();
} else {
fn->artificial = buf.getWord();
fn->Filename = buf.getString();
filename = buf.getString();
fn->startLine = buf.getWord();
fn->startColumn = buf.getWord();
fn->endLine = buf.getWord();
if (Version >= GCOV::V900)
fn->endColumn = buf.getWord();
}
auto r = filenameToIdx.try_emplace(filename, filenameToIdx.size());
if (r.second)
filenames.emplace_back(filename);
fn->srcIdx = r.first->second;
IdentToFunction[fn->ident] = fn;
} else if (tag == GCOV_TAG_BLOCKS && fn) {
if (Version < GCOV::V800) {
Expand Down Expand Up @@ -224,8 +229,8 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) {
}

void GCOVFile::print(raw_ostream &OS) const {
for (const auto &FPtr : Functions)
FPtr->print(OS);
for (const GCOVFunction &f : *this)
f.print(OS);
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Expand All @@ -235,16 +240,23 @@ LLVM_DUMP_METHOD void GCOVFile::dump() const { print(dbgs()); }

/// collectLineCounts - Collect line counts. This must be used after
/// reading .gcno and .gcda files.
void GCOVFile::collectLineCounts(FileInfo &FI) {
for (const auto &FPtr : Functions)
FPtr->collectLineCounts(FI);
FI.setRunCount(RunCount);
FI.setProgramCount(ProgramCount);
void GCOVFile::collectLineCounts(FileInfo &fi) {
assert(fi.sources.empty());
for (StringRef filename : filenames)
fi.sources.emplace_back(filename);
for (GCOVFunction &f : *this) {
f.collectLineCounts(fi);
fi.sources[f.srcIdx].functions.push_back(&f);
}
fi.setRunCount(RunCount);
fi.setProgramCount(ProgramCount);
}

//===----------------------------------------------------------------------===//
// GCOVFunction implementation.

StringRef GCOVFunction::getFilename() const { return file.filenames[srcIdx]; }

/// getEntryCount - Get the number of times the function was called by
/// retrieving the entry block's count.
uint64_t GCOVFunction::getEntryCount() const {
Expand All @@ -258,7 +270,7 @@ uint64_t GCOVFunction::getExitCount() const {
}

void GCOVFunction::print(raw_ostream &OS) const {
OS << "===== " << Name << " (" << ident << ") @ " << Filename << ":"
OS << "===== " << Name << " (" << ident << ") @ " << getFilename() << ":"
<< startLine << "\n";
for (const auto &Block : Blocks)
Block->print(OS);
Expand All @@ -279,7 +291,7 @@ void GCOVFunction::collectLineCounts(FileInfo &FI) {

for (const auto &Block : Blocks)
Block->collectLineCounts(FI);
FI.addFunctionLine(Filename, startLine, this);
FI.addFunctionLine(getFilename(), startLine, this);
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -596,8 +608,7 @@ 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,
GCOV::GCOVVersion Version) {
StringRef GCNOFile, StringRef GCDAFile, GCOVFile &file) {
SmallVector<StringRef, 4> Filenames;
for (const auto &LI : LineInfo)
Filenames.push_back(LI.first());
Expand All @@ -619,7 +630,7 @@ void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
CovOS << " -: 0:Graph:" << GCNOFile << "\n";
CovOS << " -: 0:Data:" << GCDAFile << "\n";
CovOS << " -: 0:Runs:" << RunCount << "\n";
if (Version < GCOV::V900)
if (file.getVersion() < GCOV::V900)
CovOS << " -: 0:Programs:" << ProgramCount << "\n";

const LineData &Line = LineInfo[Filename];
Expand Down Expand Up @@ -707,7 +718,9 @@ void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
}
}
}
FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
SourceInfo &source = sources[file.filenameToIdx.find(Filename)->second];
source.name = CoveragePath;
source.coverage = FileCoverage;
}

if (!Options.UseStdout) {
Expand Down Expand Up @@ -816,13 +829,12 @@ void FileInfo::printFuncCoverage(raw_ostream &OS) const {

// printFileCoverage - Print per-file coverage info.
void FileInfo::printFileCoverage(raw_ostream &OS) const {
for (const auto &FC : FileCoverages) {
const std::string &Filename = FC.first;
const GCOVCoverage &Coverage = FC.second;
for (const SourceInfo &source : sources) {
const GCOVCoverage &Coverage = source.coverage;
OS << "File '" << Coverage.Name << "'\n";
printCoverage(OS, Coverage);
if (!Options.NoOutput)
OS << "Creating '" << Filename << "'\n";
OS << "Creating '" << source.name << "'\n";
OS << "\n";
}
}
24 changes: 12 additions & 12 deletions llvm/test/tools/llvm-cov/llvm-cov.test
Expand Up @@ -131,18 +131,18 @@ RUN: FileCheck %s --check-prefixes=H,H-A,H-B --match-full-lines --strict-whitesp
OUT-FB-NEXT:Taken at least once:81.82% of 11
OUT-FB-NEXT:No calls
OUT-F-EMPTY:
OUT:File './test.h'
OUT-NEXT:Lines executed:100.00% of 1
OUT-B-NEXT:No branches
OUT-B-NEXT:No calls
OUTFILE-NEXT:Creating 'test.h.gcov'
OUT-EMPTY:
OUT-NEXT:File 'test.cpp'
OUT:File 'test.cpp'
OUT-NEXT:Lines executed:81.40% of 43
OUT-B-NEXT:Branches executed:100.00% of 15
OUT-B-NEXT:Taken at least once:86.67% of 15
OUT-B-NEXT:No calls
OUTFILE-NEXT:Creating 'test.cpp.gcov'
OUT-EMPTY:
OUT-NEXT:File './test.h'
OUT-NEXT:Lines executed:100.00% of 1
OUT-B-NEXT:No branches
OUT-B-NEXT:No calls
OUTFILE-NEXT:Creating 'test.h.gcov'

# Summarize unconditional branches too.
RUN: llvm-cov gcov test.c -a -b -u | FileCheck %s --check-prefixes=OUT,OUTFILE,OUT-B
Expand All @@ -158,13 +158,13 @@ H-C: unconditional 0 taken 1
RUN: llvm-cov gcov test.c -gcda=no_such_gcda_file | FileCheck %s --check-prefix=NO-GCDA
RUN: diff -aub test_no_gcda.cpp.gcov test.cpp.gcov
RUN: diff -aub test_no_gcda.h.gcov test.h.gcov
NO-GCDA: File './test.h'
NO-GCDA-NEXT: Lines executed:0.00% of 1
NO-GCDA-NEXT: Creating 'test.h.gcov'
NO-GCDA-EMPTY:
NO-GCDA-NEXT: File 'test.cpp'
NO-GCDA: File 'test.cpp'
NO-GCDA-NEXT: Lines executed:0.00% of 43
NO-GCDA-NEXT: Creating 'test.cpp.gcov'
NO-GCDA-EMPTY:
NO-GCDA-NEXT: File './test.h'
NO-GCDA-NEXT: Lines executed:0.00% of 1
NO-GCDA-NEXT: Creating 'test.h.gcov'

# Invalid gcno file.
RUN: llvm-cov gcov test.c -gcno=test_read_fail.gcno
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-cov/gcov.cpp
Expand Up @@ -77,7 +77,7 @@ static void reportCoverage(StringRef SourceFile, StringRef ObjectDir,

FileInfo FI(Options);
GF.collectLineCounts(FI);
FI.print(llvm::outs(), SourceFile, GCNO, GCDA, GF.getVersion());
FI.print(llvm::outs(), SourceFile, GCNO, GCDA, GF);
}

int gcovMain(int argc, const char *argv[]) {
Expand Down

0 comments on commit 4cd7ba7

Please sign in to comment.