[PATCH] llvm-cov: Print coverage summary to STDOUT.

Justin Bogner mail at justinbogner.com
Thu Dec 12 18:48:38 PST 2013


Yuchen Wu <yuchenericwu at hotmail.com> writes:
> From 6eb0174daa640ae4b655408e6e35087f3284e7a6 Mon Sep 17 00:00:00 2001
> From: Yuchen Wu <yuchen_wu at apple.com>
> Date: Thu, 12 Dec 2013 12:21:11 -0800
> Subject: [PATCH 3/5] llvm-cov: Print coverage summary to STDOUT.
>
> File summaries will now be optionally outputted which will give line,
> branching and call coverage info. Unfortunately, clang's current
> instrumentation does not give enough information to deduce function
> calls, something that gcc is able to do. Thus, no calls are always
> outputted to be consistent with gcov output.
>
> Also updated tests.
> ---
>  include/llvm/Support/GCOV.h                       | 16 ++++++++-
>  lib/IR/GCOV.cpp                                   | 42 +++++++++++++++++++----
>  test/tools/llvm-cov/Inputs/test_-b.output         | 13 +++++++
>  test/tools/llvm-cov/Inputs/test_no_options.output |  8 +++++
>  test/tools/llvm-cov/llvm-cov.test                 |  4 +--
>  5 files changed, 74 insertions(+), 9 deletions(-)
>  create mode 100644 test/tools/llvm-cov/Inputs/test_-b.output
>  create mode 100644 test/tools/llvm-cov/Inputs/test_no_options.output
>
> diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h
> index c3018f1..42fdcff 100644
> --- a/include/llvm/Support/GCOV.h
> +++ b/include/llvm/Support/GCOV.h
> @@ -350,6 +350,19 @@ class FileInfo {
>      BlockLines Blocks;
>      FunctionLines Functions;
>    };
> +
> +  struct GCOVSummary {
> +    GCOVSummary() :
> +      LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0),
> +      BranchesTaken(0) {}
> +
> +    uint32_t LogicalLines;
> +    uint32_t LinesExec;
> +
> +    uint32_t Branches;
> +    uint32_t BranchesExec;
> +    uint32_t BranchesTaken;
> +  };
>  public:
>    FileInfo(const GCOVOptions &Options) :
>      Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
> @@ -369,7 +382,8 @@ public:
>    void printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
>                        uint32_t LineIndex, uint32_t &BlockNo) const;
>    void printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
> -                       uint32_t LineIndex, uint32_t &EdgeNo) const;
> +                       GCOVSummary &Summary, uint32_t LineIndex,
> +                       uint32_t &EdgeNo) const;
>  private:
>    const GCOVOptions &Options;
>    StringMap<LineData> LineInfo;
> diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp
> index 7902f04..fc626ca 100644
> --- a/lib/IR/GCOV.cpp
> +++ b/lib/IR/GCOV.cpp
> @@ -430,6 +430,7 @@ void FileInfo::print(StringRef GCNOFile, StringRef GCDAFile) const {
>      OS << "        -:    0:Programs:" << ProgramCount << "\n";
>  
>      const LineData &Line = I->second;
> +    GCOVSummary Summary;
>      for (uint32_t LineIndex = 0; !AllLines.empty(); ++LineIndex) {
>        if (Options.BranchInfo) {
>          FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
> @@ -461,10 +462,14 @@ void FileInfo::print(StringRef GCNOFile, StringRef GCDAFile) const {
>              LineCount += Block->getCount();
>            }
>          }
> +
>          if (LineCount == 0)
>            OS << "    #####:";
> -        else
> +        else {
>            OS << format("%9" PRIu64 ":", LineCount);
> +          ++Summary.LinesExec;
> +        }
> +        ++Summary.LogicalLines;
>  
>          std::pair<StringRef, StringRef> P = AllLines.split('\n');
>          OS << format("%5u:", LineIndex+1) << P.first << "\n";
> @@ -482,10 +487,31 @@ void FileInfo::print(StringRef GCNOFile, StringRef GCDAFile) const {
>            if (Options.AllBlocks)
>              printBlockInfo(OS, *Block, LineIndex, BlockNo);
>            if (Options.BranchInfo)
> -            printBranchInfo(OS, *Block, LineIndex, EdgeNo);
> +            printBranchInfo(OS, *Block, Summary, LineIndex, EdgeNo);
>          }
>        }
>      }
> +
> +    // FIXME: There is no way to detect calls given current instrumentation.
> +    outs() << "File '" << Filename << "'\n";
> +    outs() << format("Lines executed:%.2lf%% of %u\n",
> +                     double(Summary.LinesExec)*100/Summary.LogicalLines,
> +                     Summary.LogicalLines);
> +    if (Options.BranchInfo) {
> +      if (Summary.Branches) {
> +        outs() << format("Branches executed:%.2lf%% of %u\n",
> +                         double(Summary.BranchesExec)*100/Summary.Branches,
> +                         Summary.Branches);
> +        outs() << format("Taken at least once:%.2lf%% of %u\n",
> +                         double(Summary.BranchesTaken)*100/Summary.Branches,
> +                         Summary.Branches);
> +      } else {
> +        outs() << "No branches\n";
> +      }
> +      outs() << "No calls\n"; // to be consistent with gcov
> +    }
> +    outs() << Filename << ":creating '" << CovFilename << "'\n";
> +    outs() << "\n";

Might as well pull this out into a "printSummary" function.

>    }
>  }
>  
> @@ -496,18 +522,18 @@ void FileInfo::printFunctionSummary(raw_fd_ostream &OS,
>           I != E; ++I) {
>      const GCOVFunction *Func = *I;
>      uint64_t EntryCount = Func->getEntryCount();
> -    uint32_t BlocksExecuted = 0;
> +    uint32_t BlocksExec = 0;

Why rename this?

>      for (GCOVFunction::BlockIterator I = Func->block_begin(),
>             E = Func->block_end(); I != E; ++I) {
>        const GCOVBlock *Block = *I;
>        if (Block->getNumDstEdges() && Block->getCount())
> -          ++BlocksExecuted;
> +          ++BlocksExec;
>      }
>  
>      OS << "function " << Func->getName() << " called " << EntryCount
>         << " returned " << safeDiv(Func->getExitCount()*100, EntryCount)
>         << "% blocks executed "
> -       << safeDiv(BlocksExecuted*100, Func->getNumBlocks()-1) << "%\n";
> +       << safeDiv(BlocksExec*100, Func->getNumBlocks()-1) << "%\n";
>    }
>  }
>  
> @@ -523,7 +549,8 @@ void FileInfo::printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
>  
>  /// printBranchInfo - Print branch probabilities.
>  void FileInfo::printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
> -                               uint32_t LineIndex, uint32_t &EdgeNo) const {
> +                               GCOVSummary &Summary, uint32_t LineIndex,
> +                               uint32_t &EdgeNo) const {
>    size_t NumEdges = Block.getNumDstEdges();
>    if (NumEdges > 1) {
>      // Print conditional branch info.
> @@ -534,6 +561,9 @@ void FileInfo::printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
>        const GCOVEdge *Edge = *I;
>        BranchCounts.push_back(Edge->Count);
>        TotalCounts += Edge->Count;
> +      if (Block.getCount()) ++Summary.BranchesExec;
> +      if (Edge->Count) ++Summary.BranchesTaken;
> +      ++Summary.Branches;
>      }
>  
>      for (SmallVectorImpl<uint64_t>::const_iterator I = BranchCounts.begin(),
> diff --git a/test/tools/llvm-cov/Inputs/test_-b.output b/test/tools/llvm-cov/Inputs/test_-b.output
> new file mode 100644
> index 0000000..4003ce8
> --- /dev/null
> +++ b/test/tools/llvm-cov/Inputs/test_-b.output
> @@ -0,0 +1,13 @@
> +File 'test.cpp'
> +Lines executed:84.21% of 38
> +Branches executed:100.00% of 15
> +Taken at least once:86.67% of 15
> +No calls
> +test.cpp:creating 'test.cpp.gcov'
> +
> +File './test.h'
> +Lines executed:100.00% of 1
> +No branches
> +No calls
> +./test.h:creating './test.h.gcov'
> +
> diff --git a/test/tools/llvm-cov/Inputs/test_no_options.output b/test/tools/llvm-cov/Inputs/test_no_options.output
> new file mode 100644
> index 0000000..93ea726
> --- /dev/null
> +++ b/test/tools/llvm-cov/Inputs/test_no_options.output
> @@ -0,0 +1,8 @@
> +File 'test.cpp'
> +Lines executed:84.21% of 38
> +test.cpp:creating 'test.cpp.gcov'
> +
> +File './test.h'
> +Lines executed:100.00% of 1
> +./test.h:creating './test.h.gcov'
> +
> diff --git a/test/tools/llvm-cov/llvm-cov.test b/test/tools/llvm-cov/llvm-cov.test
> index 02b8a3d..da39307 100644
> --- a/test/tools/llvm-cov/llvm-cov.test
> +++ b/test/tools/llvm-cov/llvm-cov.test
> @@ -5,7 +5,7 @@ RUN: mkdir %t
>  RUN: cd %t
>  RUN: cp %p/Inputs/test* .
>  
> -RUN: llvm-cov -gcno=test.gcno -gcda=test.gcda
> +RUN: llvm-cov -gcno=test.gcno -gcda=test.gcda | diff test_no_options.output -
>  RUN: diff -aub test_no_options.cpp.gcov test.cpp.gcov
>  RUN: diff -aub test_no_options.h.gcov test.h.gcov
>  
> @@ -13,7 +13,7 @@ RUN: llvm-cov -gcno=test.gcno -gcda=test.gcda -a
>  RUN: diff -aub test_-a.cpp.gcov test.cpp.gcov
>  RUN: diff -aub test_-a.h.gcov test.h.gcov
>  
> -RUN: llvm-cov -gcno=test.gcno -gcda=test.gcda -a -b
> +RUN: llvm-cov -gcno=test.gcno -gcda=test.gcda -a -b | diff test_-b.output -
>  RUN: diff -aub test_-a_-b.cpp.gcov test.cpp.gcov
>  RUN: diff -aub test_-a_-b.h.gcov test.h.gcov



More information about the llvm-commits mailing list