1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[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.
This commit is contained in:
Fangrui Song 2021-06-19 22:51:20 -07:00
parent f02bea7812
commit 9e8233e08c
5 changed files with 64 additions and 15 deletions

View File

@ -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 @@ public:
}
/// 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 @@ public:
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 @@ public:
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 @@ public:
private:
MemoryBuffer *Buffer;
GCOV::GCOVVersion version{};
};
/// GCOVFile - Collects coverage information for one pair of coverage file
@ -199,7 +206,7 @@ public:
public:
bool GCNOInitialized = false;
GCOV::GCOVVersion version;
GCOV::GCOVVersion version{};
uint32_t checksum = 0;
StringRef cwd;
SmallVector<std::unique_ptr<GCOVFunction>, 16> functions;

View File

@ -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());

Binary file not shown.

Binary file not shown.

View File

@ -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