[llvm] 0873016 - [llvm-cov gcov] Support GCC 12 format

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 19 22:51:34 PDT 2021


Author: Fangrui Song
Date: 2021-06-19T22:51:20-07:00
New Revision: 0873016ceff3ded84bfeaa37b39be675fa178f7d

URL: https://github.com/llvm/llvm-project/commit/0873016ceff3ded84bfeaa37b39be675fa178f7d
DIFF: https://github.com/llvm/llvm-project/commit/0873016ceff3ded84bfeaa37b39be675fa178f7d.diff

LOG: [llvm-cov gcov] Support GCC 12 format

GCC 12 will change the length field to represent the number of bytes instead of
32-bit words. This avoids padding for strings.

Added: 
    llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcda
    llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcno
    llvm/test/tools/llvm-cov/gcov/gcov-12.c

Modified: 
    llvm/include/llvm/ProfileData/GCOV.h
    llvm/lib/ProfileData/GCOV.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ProfileData/GCOV.h b/llvm/include/llvm/ProfileData/GCOV.h
index 01db686819d7b..ef6515d391440 100644
--- a/llvm/include/llvm/ProfileData/GCOV.h
+++ b/llvm/include/llvm/ProfileData/GCOV.h
@@ -42,7 +42,7 @@ class GCOVBlock;
 
 namespace GCOV {
 
-enum GCOVVersion { V304, V407, V408, V800, V900 };
+enum GCOVVersion { V304, V407, V408, V800, V900, V1200 };
 
 /// A struct for passing gcov options between functions.
 struct Options {
@@ -108,7 +108,7 @@ class GCOVBuffer {
   }
 
   /// readGCOVVersion - Read GCOV version.
-  bool readGCOVVersion(GCOV::GCOVVersion &Version) {
+  bool readGCOVVersion(GCOV::GCOVVersion &version) {
     std::string str(de.getBytes(cursor, 4));
     if (str.size() != 4)
       return false;
@@ -117,24 +117,27 @@ class GCOVBuffer {
     int ver = str[0] >= 'A'
                   ? (str[0] - 'A') * 100 + (str[1] - '0') * 10 + str[2] - '0'
                   : (str[0] - '0') * 10 + str[2] - '0';
-    if (ver >= 90) {
+    if (ver >= 120) {
+      this->version = version = GCOV::V1200;
+      return true;
+    } else if (ver >= 90) {
       // PR gcov-profile/84846, r269678
-      Version = GCOV::V900;
+      this->version = version = GCOV::V900;
       return true;
     } else if (ver >= 80) {
       // PR gcov-profile/48463
-      Version = GCOV::V800;
+      this->version = version = GCOV::V800;
       return true;
     } else if (ver >= 48) {
       // r189778: the exit block moved from the last to the second.
-      Version = GCOV::V408;
+      this->version = version = GCOV::V408;
       return true;
     } else if (ver >= 47) {
       // r173147: split checksum into cfg checksum and line checksum.
-      Version = GCOV::V407;
+      this->version = version = GCOV::V407;
       return true;
     } else if (ver >= 34) {
-      Version = GCOV::V304;
+      this->version = version = GCOV::V304;
       return true;
     }
     errs() << "unexpected version: " << str << "\n";
@@ -167,11 +170,14 @@ class GCOVBuffer {
     return true;
   }
 
-  bool readString(StringRef &Str) {
+  bool readString(StringRef &str) {
     uint32_t len;
     if (!readInt(len) || len == 0)
       return false;
-    Str = de.getBytes(cursor, len * 4).split('\0').first;
+    if (version >= GCOV::V1200)
+      str = de.getBytes(cursor, len).drop_back();
+    else
+      str = de.getBytes(cursor, len * 4).split('\0').first;
     return bool(cursor);
   }
 
@@ -180,6 +186,7 @@ class GCOVBuffer {
 
 private:
   MemoryBuffer *Buffer;
+  GCOV::GCOVVersion version{};
 };
 
 /// GCOVFile - Collects coverage information for one pair of coverage file
@@ -199,7 +206,7 @@ class GCOVFile {
 
 public:
   bool GCNOInitialized = false;
-  GCOV::GCOVVersion version;
+  GCOV::GCOVVersion version{};
   uint32_t checksum = 0;
   StringRef cwd;
   SmallVector<std::unique_ptr<GCOVFunction>, 16> functions;

diff  --git a/llvm/lib/ProfileData/GCOV.cpp b/llvm/lib/ProfileData/GCOV.cpp
index f3095cf7fcca9..afef71f5b5ad0 100644
--- a/llvm/lib/ProfileData/GCOV.cpp
+++ b/llvm/lib/ProfileData/GCOV.cpp
@@ -115,6 +115,7 @@ bool GCOVFile::readGCNO(GCOVBuffer &buf) {
   while ((tag = buf.getWord())) {
     if (!buf.readInt(length))
       return false;
+    uint32_t pos = buf.cursor.tell();
     if (tag == GCOV_TAG_FUNCTION) {
       functions.push_back(std::make_unique<GCOVFunction>(*this));
       fn = functions.back().get();
@@ -162,7 +163,9 @@ bool GCOVFile::readGCNO(GCOVBuffer &buf) {
         return false;
       }
       GCOVBlock *src = fn->blocks[srcNo].get();
-      for (uint32_t i = 0, e = (length - 1) / 2; i != e; ++i) {
+      const uint32_t e =
+          version >= GCOV::V1200 ? (length / 4 - 1) / 2 : (length - 1) / 2;
+      for (uint32_t i = 0; i != e; ++i) {
         uint32_t dstNo = buf.getWord(), flags = buf.getWord();
         GCOVBlock *dst = fn->blocks[dstNo].get();
         auto arc = std::make_unique<GCOVArc>(*src, *dst, flags);
@@ -194,6 +197,10 @@ bool GCOVFile::readGCNO(GCOVBuffer &buf) {
         }
       }
     }
+    pos += version >= GCOV::V1200 ? length : 4 * length;
+    if (pos < buf.cursor.tell())
+      return false;
+    buf.de.skip(buf.cursor, pos - buf.cursor.tell());
   }
 
   GCNOInitialized = true;
@@ -268,11 +275,14 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) {
         }
       }
     } else if (tag == GCOV_TAG_COUNTER_ARCS && fn) {
-      if (length != 2 * fn->arcs.size()) {
+      uint32_t expected = 2 * fn->arcs.size();
+      if (version >= GCOV::V1200)
+        expected *= 4;
+      if (length != expected) {
         errs() << fn->Name
                << format(
                       ": GCOV_TAG_COUNTER_ARCS mismatch, got %u, expected %u\n",
-                      length, unsigned(2 * fn->arcs.size()));
+                      length, expected);
         return false;
       }
       for (std::unique_ptr<GCOVArc> &arc : fn->arcs) {
@@ -296,7 +306,7 @@ bool GCOVFile::readGCDA(GCOVBuffer &buf) {
           fn->treeArcs[i - 1]->src.count += fn->treeArcs[i - 1]->count;
       }
     }
-    pos += 4 * length;
+    pos += version >= GCOV::V1200 ? length : 4 * length;
     if (pos < buf.cursor.tell())
       return false;
     buf.de.skip(buf.cursor, pos - buf.cursor.tell());

diff  --git a/llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcda b/llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcda
new file mode 100644
index 0000000000000..8ceec1db53a47
Binary files /dev/null and b/llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcda 
diff er

diff  --git a/llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcno b/llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcno
new file mode 100644
index 0000000000000..f91e6258c8b68
Binary files /dev/null and b/llvm/test/tools/llvm-cov/gcov/Inputs/gcov-12.gcno 
diff er

diff  --git a/llvm/test/tools/llvm-cov/gcov/gcov-12.c b/llvm/test/tools/llvm-cov/gcov/gcov-12.c
new file mode 100644
index 0000000000000..5e754f5b9cccb
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/gcov/gcov-12.c
@@ -0,0 +1,32 @@
+/// Test that llvm-cov supports gcov 12 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: 12: [[@LINE]]:
+    result = sqrt(fabs(a[i])) + 5 * pow(a[i], 3); // GCOV-NEXT: 11: [[@LINE]]:
+    printf("\nf(%d) = ", i);                      // GCOV-NEXT: 11: [[@LINE]]:
+    if (result > 400) printf("Overflow!");        // GCOV-NEXT: 11: [[@LINE]]:
+    else printf("%lf", result);                   // GCOV-NEXT:  4: [[@LINE]]:
+  }                                               // GCOV-NEXT:  -: [[@LINE]]:
+  return 0;                                       // GCOV-NEXT:  1: [[@LINE]]:
+}                                                 // GCOV-NEXT:  -: [[@LINE]]:
+
+// RUN: rm -rf %t && mkdir %t && cd %t
+// RUN: cp %s %p/Inputs/gcov-12.gc* .
+
+// RUN: llvm-cov gcov gcov-12.c | FileCheck %s
+// CHECK:      File 'gcov-12.c'
+// CHECK-NEXT: Lines executed:100.00% of 9
+// CHECK-NEXT: Creating 'gcov-12.c.gcov'
+
+// RUN: FileCheck --input-file=%t/gcov-12.c.gcov --check-prefix=HEADER %s
+// RUN: FileCheck --input-file=%t/gcov-12.c.gcov --check-prefix=GCOV %s
+
+// HEADER: {{^}} -:    0:Source:gcov-12.c
+// HEADER-NEXT:  -:    0:Graph:gcov-12.gcno
+// HEADER-NEXT:  -:    0:Data:gcov-12.gcda
+// HEADER-NEXT:  -:    0:Runs:1{{$}}
+// HEADER-NEXT:  -:    1:/// Test that llvm-cov


        


More information about the llvm-commits mailing list