[llvm] r200754 - llvm-cov: Implement the preserve-paths flag

Justin Bogner mail at justinbogner.com
Tue Feb 4 02:45:02 PST 2014


Author: bogner
Date: Tue Feb  4 04:45:02 2014
New Revision: 200754

URL: http://llvm.org/viewvc/llvm-project?rev=200754&view=rev
Log:
llvm-cov: Implement the preserve-paths flag

Until now, when a path in a gcno file included a directory, we would
emit our .gcov file in that directory, whereas gcov always emits the
file in the current directory. In doing so, this implements gcov's
strange name-mangling -p flag, which is needed to avoid clobbering
files when two with the same name exist in different directories.

The path mangling is a bit ugly and only handles unix-like paths, but
it's simple, and it doesn't make any guesses as to how it should
behave outside of what gcov documents. If we decide this should be
cross platform later, we can consider the compatibility implications
then.

Added:
    llvm/trunk/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output
    llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov
    llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcda
    llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcno
    llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.h.gcov
    llvm/trunk/test/tools/llvm-cov/Inputs/test_preserve_paths.output
Modified:
    llvm/trunk/include/llvm/Support/GCOV.h
    llvm/trunk/lib/IR/GCOV.cpp
    llvm/trunk/test/tools/llvm-cov/Inputs/test_-b.output
    llvm/trunk/test/tools/llvm-cov/Inputs/test_-f.output
    llvm/trunk/test/tools/llvm-cov/Inputs/test_no_gcda.output
    llvm/trunk/test/tools/llvm-cov/Inputs/test_no_options.output
    llvm/trunk/test/tools/llvm-cov/llvm-cov.test
    llvm/trunk/tools/llvm-cov/llvm-cov.cpp

Modified: llvm/trunk/include/llvm/Support/GCOV.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/GCOV.h?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/GCOV.h (original)
+++ llvm/trunk/include/llvm/Support/GCOV.h Tue Feb  4 04:45:02 2014
@@ -37,14 +37,15 @@ namespace GCOV {
 
 /// GCOVOptions - A struct for passing gcov options between functions.
 struct GCOVOptions {
-  GCOVOptions(bool A, bool B, bool C, bool F, bool U) :
-    AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), UncondBranch(U)
-  {}
+  GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U)
+      : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
+        PreservePaths(P), UncondBranch(U) {}
 
   bool AllBlocks;
   bool BranchInfo;
   bool BranchCount;
   bool FuncCoverage;
+  bool PreservePaths;
   bool UncondBranch;
 };
 
@@ -401,8 +402,13 @@ private:
   StringMap<LineData> LineInfo;
   uint32_t RunCount;
   uint32_t ProgramCount;
-  SmallVector<GCOVCoverage, 4> FileCoverages;
-  MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverages;
+
+  typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4>
+      FileCoverageList;
+  typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
+
+  FileCoverageList FileCoverages;
+  FuncCoverageMap FuncCoverages;
 };
 
 }

Modified: llvm/trunk/lib/IR/GCOV.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/GCOV.cpp?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/lib/IR/GCOV.cpp (original)
+++ llvm/trunk/lib/IR/GCOV.cpp Tue Feb  4 04:45:02 2014
@@ -16,8 +16,10 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/GCOV.h"
 #include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/system_error.h"
 #include <algorithm>
 using namespace llvm;
@@ -429,6 +431,42 @@ static raw_ostream &operator<<(raw_ostre
   return OS;
 }
 
+/// Convert a path to a gcov filename. If PreservePaths is true, this
+/// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
+static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
+  if (!PreservePaths)
+    return (sys::path::filename(Filename) + ".gcov").str();
+
+  // This behaviour is defined by gcov in terms of text replacements, so it's
+  // not likely to do anything useful on filesystems with different textual
+  // conventions.
+  llvm::SmallString<256> Result("");
+  StringRef::iterator I, S, E;
+  for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
+    if (*I != '/')
+      continue;
+
+    if (I - S == 1 && *S == '.') {
+      // ".", the current directory, is skipped.
+    } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
+      // "..", the parent directory, is replaced with "^".
+      Result.append("^#");
+    } else {
+      if (S < I)
+        // Leave other components intact,
+        Result.append(S, I);
+      // And separate with "#".
+      Result.push_back('#');
+    }
+    S = I + 1;
+  }
+
+  if (S < I)
+    Result.append(S, I);
+  Result.append(".gcov");
+  return Result.str();
+}
+
 /// print -  Print source files with collected line count information.
 void FileInfo::print(StringRef GCNOFile, StringRef GCDAFile) {
   for (StringMap<LineData>::const_iterator I = LineInfo.begin(),
@@ -441,9 +479,10 @@ void FileInfo::print(StringRef GCNOFile,
     }
     StringRef AllLines = Buff->getBuffer();
 
-    std::string CovFilename = Filename.str() + ".gcov";
+    std::string CoveragePath = mangleCoveragePath(Filename,
+                                                  Options.PreservePaths);
     std::string ErrorInfo;
-    raw_fd_ostream OS(CovFilename.c_str(), ErrorInfo);
+    raw_fd_ostream OS(CoveragePath.c_str(), ErrorInfo);
     if (!ErrorInfo.empty())
       errs() << ErrorInfo << "\n";
 
@@ -555,7 +594,7 @@ void FileInfo::print(StringRef GCNOFile,
         }
       }
     }
-    FileCoverages.push_back(FileCoverage);
+    FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
   }
 
   // FIXME: There is no way to detect calls given current instrumentation.
@@ -656,8 +695,8 @@ void FileInfo::printCoverage(const GCOVC
 
 // printFuncCoverage - Print per-function coverage info.
 void FileInfo::printFuncCoverage() const {
-  for (MapVector<const GCOVFunction *, GCOVCoverage>::const_iterator I =
-         FuncCoverages.begin(), E = FuncCoverages.end(); I != E; ++I) {
+  for (FuncCoverageMap::const_iterator I = FuncCoverages.begin(),
+                                       E = FuncCoverages.end(); I != E; ++I) {
     const GCOVCoverage &Coverage = I->second;
     outs() << "Function '" << Coverage.Name << "'\n";
     printCoverage(Coverage);
@@ -667,12 +706,12 @@ void FileInfo::printFuncCoverage() const
 
 // printFileCoverage - Print per-file coverage info.
 void FileInfo::printFileCoverage() const {
-  for (SmallVectorImpl<GCOVCoverage>::const_iterator I =
-         FileCoverages.begin(), E = FileCoverages.end(); I != E; ++I) {
-    const GCOVCoverage &Coverage = *I;
+  for (FileCoverageList::const_iterator I = FileCoverages.begin(),
+                                        E = FileCoverages.end(); I != E; ++I) {
+    const std::string &Filename = I->first;
+    const GCOVCoverage &Coverage = I->second;
     outs() << "File '" << Coverage.Name << "'\n";
     printCoverage(Coverage);
-    outs() << Coverage.Name << ":creating '" << Coverage.Name
-           << ".gcov'\n\n";
+    outs() << Coverage.Name << ":creating '" << Filename << "'\n\n";
   }
 }

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test_-b.output
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_-b.output?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_-b.output (original)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_-b.output Tue Feb  4 04:45:02 2014
@@ -9,5 +9,5 @@ File './test.h'
 Lines executed:100.00% of 1
 No branches
 No calls
-./test.h:creating './test.h.gcov'
+./test.h:creating 'test.h.gcov'
 

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test_-f.output
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_-f.output?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_-f.output (original)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_-f.output Tue Feb  4 04:45:02 2014
@@ -34,5 +34,5 @@ test.cpp:creating 'test.cpp.gcov'
 
 File './test.h'
 Lines executed:100.00% of 1
-./test.h:creating './test.h.gcov'
+./test.h:creating 'test.h.gcov'
 

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test_no_gcda.output
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_no_gcda.output?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_no_gcda.output (original)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_no_gcda.output Tue Feb  4 04:45:02 2014
@@ -4,5 +4,5 @@ test.cpp:creating 'test.cpp.gcov'
 
 File './test.h'
 Lines executed:0.00% of 1
-./test.h:creating './test.h.gcov'
+./test.h:creating 'test.h.gcov'
 

Modified: llvm/trunk/test/tools/llvm-cov/Inputs/test_no_options.output
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_no_options.output?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_no_options.output (original)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_no_options.output Tue Feb  4 04:45:02 2014
@@ -4,5 +4,5 @@ test.cpp:creating 'test.cpp.gcov'
 
 File './test.h'
 Lines executed:100.00% of 1
-./test.h:creating './test.h.gcov'
+./test.h:creating 'test.h.gcov'
 

Added: llvm/trunk/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output?rev=200754&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_no_preserve_paths.output Tue Feb  4 04:45:02 2014
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'test.h.gcov'
+
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'test.cpp.gcov'
+

Added: llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov?rev=200754&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.cpp.gcov Tue Feb  4 04:45:02 2014
@@ -0,0 +1,79 @@
+        -:    0:Source:srcdir/./nested_dir/../test.cpp
+        -:    0:Graph:test_paths.gcno
+        -:    0:Data:test_paths.gcda
+        -:    0:Runs:3
+        -:    0:Programs:1
+        -:    1:#include "test.h"
+        -:    2:#include <cstdlib>
+        -:    3:
+        -:    4:bool on = false;
+        -:    5:int len = 42;
+        -:    6:double grid[10][10] = {0};
+        -:    7:const char * hello = "world";
+        -:    8:const char * world = "hello";
+        -:    9:
+12884901888:   10:void A::B() {}
+        -:   11:
+    #####:   12:void useless() {}
+        -:   13:
+        -:   14:double more_useless() {
+    #####:   15:  return 0;
+        -:   16:}
+        -:   17:
+        -:   18:int foo() {
+        3:   19:  on = true;
+        3:   20:  return 3;
+        -:   21:}
+        -:   22:
+        -:   23:int bar() {
+    #####:   24:  len--;
+    #####:   25:  return foo() + 45;
+        -:   26:}
+        -:   27:
+       12:   28:void assign(int ii, int jj) {
+       12:   29:  grid[ii][jj] = (ii+1) * (jj+1);
+       12:   30:}
+        -:   31:
+        -:   32:void initialize_grid() {
+       21:   33:  for (int ii = 0; ii < 2; ii++)
+       36:   34:    for (int jj = 0; jj < 2; jj++)
+       18:   35:      assign(ii, jj);
+        3:   36:}
+        -:   37:
+        -:   38:int main() {
+        3:   39:  initialize_grid();
+        -:   40:
+        3:   41:  int a = 2;
+        3:   42:  on = rand() % 2;
+        3:   43:  if (on) {
+        3:   44:    foo();
+        3:   45:    ++a;
+        3:   46:  } else {
+    #####:   47:    bar();
+    #####:   48:    a += rand();
+        -:   49:  }
+        -:   50:
+       66:   51:  for (int ii = 0; ii < 10; ++ii) {
+       30:   52:    switch (rand() % 5) {
+        -:   53:      case 0:
+        6:   54:        a += rand();
+        6:   55:        break;
+        -:   56:      case 1:
+        -:   57:      case 2:
+        3:   58:        a += rand() / rand();
+        3:   59:        break;
+        -:   60:      case 3:
+        9:   61:        a -= rand();
+        9:   62:        break;
+        -:   63:      default:
+       12:   64:        a = -1;
+       12:   65:    }
+       30:   66:  }
+        -:   67:
+        3:   68:  A thing;
+25769803782:   69:  for (uint64_t ii = 0; ii < 4294967296; ++ii)
+12884901888:   70:    thing.B();
+        -:   71:
+        3:   72:  return a + 8 + grid[2][3] + len;
+        -:   73:  return more_useless();
+        -:   74:}

Added: llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcda
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcda?rev=200754&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcda (added) and llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcda Tue Feb  4 04:45:02 2014 differ

Added: llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcno
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcno?rev=200754&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcno (added) and llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.gcno Tue Feb  4 04:45:02 2014 differ

Added: llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.h.gcov
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.h.gcov?rev=200754&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.h.gcov (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_paths.h.gcov Tue Feb  4 04:45:02 2014
@@ -0,0 +1,8 @@
+        -:    0:Source:srcdir/./nested_dir/../test.h
+        -:    0:Graph:test_paths.gcno
+        -:    0:Data:test_paths.gcda
+        -:    0:Runs:3
+        -:    0:Programs:1
+        6:    1:struct A {
+        -:    2:  virtual void B();
+        -:    3:};

Added: llvm/trunk/test/tools/llvm-cov/Inputs/test_preserve_paths.output
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/test_preserve_paths.output?rev=200754&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/test_preserve_paths.output (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/test_preserve_paths.output Tue Feb  4 04:45:02 2014
@@ -0,0 +1,8 @@
+File 'srcdir/./nested_dir/../test.h'
+Lines executed:100.00% of 1
+srcdir/./nested_dir/../test.h:creating 'srcdir#nested_dir#^#test.h.gcov'
+
+File 'srcdir/./nested_dir/../test.cpp'
+Lines executed:84.21% of 38
+srcdir/./nested_dir/../test.cpp:creating 'srcdir#nested_dir#^#test.cpp.gcov'
+

Modified: llvm/trunk/test/tools/llvm-cov/llvm-cov.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/llvm-cov.test?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/llvm-cov.test (original)
+++ llvm/trunk/test/tools/llvm-cov/llvm-cov.test Tue Feb  4 04:45:02 2014
@@ -21,6 +21,18 @@ RUN: llvm-cov -o objdir test.c | diff -u
 RUN: diff -aub test_objdir.cpp.gcov test.cpp.gcov
 RUN: diff -aub test_objdir.h.gcov test.h.gcov
 
+# Preserve paths. This mangles the output filenames.
+RUN: mkdir -p %t/srcdir/nested_dir
+RUN: cp test.cpp test.h %t/srcdir
+RUN: llvm-cov -p test_paths.cpp | diff -u test_preserve_paths.output -
+RUN: diff -aub test_paths.cpp.gcov srcdir#nested_dir#^#test.cpp.gcov
+RUN: diff -aub test_paths.h.gcov srcdir#nested_dir#^#test.h.gcov
+
+# Don't preserve paths. Same results as preserve paths, but no mangling.
+RUN: llvm-cov test_paths.cpp | diff -u test_no_preserve_paths.output -
+RUN: diff -aub test_paths.cpp.gcov test.cpp.gcov
+RUN: diff -aub test_paths.h.gcov test.h.gcov
+
 # Function summaries. This changes stdout, but not the gcov files.
 RUN: llvm-cov test.c -f | diff -u test_-f.output -
 RUN: diff -aub test_no_options.cpp.gcov test.cpp.gcov

Modified: llvm/trunk/tools/llvm-cov/llvm-cov.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/llvm-cov.cpp?rev=200754&r1=200753&r2=200754&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/llvm-cov.cpp (original)
+++ llvm/trunk/tools/llvm-cov/llvm-cov.cpp Tue Feb  4 04:45:02 2014
@@ -47,6 +47,10 @@ static cl::opt<std::string> ObjectDir("o
                                       cl::desc("Search for objects in DIR"));
 static cl::alias ObjectDirA("object-directory", cl::aliasopt(ObjectDir));
 
+static cl::opt<bool> PreservePaths("p", cl::init(false),
+                                   cl::desc("Preserve path components"));
+static cl::alias PreservePathsA("preserve-paths", cl::aliasopt(PreservePaths));
+
 static cl::opt<bool> UncondBranch("u", cl::init(false),
                                   cl::desc("Display unconditional branch info "
                                            "(requires -b)"));
@@ -113,7 +117,7 @@ int main(int argc, char **argv) {
     GF.dump();
 
   GCOVOptions Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
-                      UncondBranch);
+                      PreservePaths, UncondBranch);
   FileInfo FI(Options);
   GF.collectLineCounts(FI);
   FI.print(InputGCNO, InputGCDA);





More information about the llvm-commits mailing list