mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 10:32:48 +02:00
[gcov] Add -i --intermediate-format
Between gcov 4.9~8, `gcov -i $file` prints coverage information to $file.gcov in an intermediate text format (single file, instead of $source.gcov for each source file). lcov newer than 2019-05-24 detects -i support and uses it to increase processing speed. gcov 9 (GCC r265587) removed --intermediate-format and -i was changed to mean --json-format. However, we consider this format still useful and support it. geninfo (part of lcov) supports this format even if we announce that we are compatible with gcov 9.0.0
This commit is contained in:
parent
69837fa7b5
commit
d1d0909fd1
@ -46,11 +46,11 @@ enum GCOVVersion { V304, V407, V408, V800, V900 };
|
||||
|
||||
/// A struct for passing gcov options between functions.
|
||||
struct Options {
|
||||
Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N,
|
||||
bool T, bool X)
|
||||
Options(bool A, bool B, bool C, bool F, bool P, bool U, bool I, bool L,
|
||||
bool N, bool T, bool X)
|
||||
: AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F),
|
||||
PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N),
|
||||
UseStdout(T), HashFilenames(X) {}
|
||||
PreservePaths(P), UncondBranch(U), Intermediate(I), LongFileNames(L),
|
||||
NoOutput(N), UseStdout(T), HashFilenames(X) {}
|
||||
|
||||
bool AllBlocks;
|
||||
bool BranchInfo;
|
||||
@ -58,6 +58,7 @@ struct Options {
|
||||
bool FuncCoverage;
|
||||
bool PreservePaths;
|
||||
bool UncondBranch;
|
||||
bool Intermediate;
|
||||
bool LongFileNames;
|
||||
bool NoOutput;
|
||||
bool UseStdout;
|
||||
|
@ -512,6 +512,7 @@ class LineConsumer {
|
||||
StringRef Remaining;
|
||||
|
||||
public:
|
||||
LineConsumer() = default;
|
||||
LineConsumer(StringRef Filename) {
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
|
||||
MemoryBuffer::getFileOrSTDIN(Filename);
|
||||
@ -615,11 +616,11 @@ void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
|
||||
llvm::sort(Filenames);
|
||||
|
||||
for (StringRef Filename : Filenames) {
|
||||
auto AllLines = LineConsumer(Filename);
|
||||
|
||||
auto AllLines =
|
||||
Options.Intermediate ? LineConsumer() : LineConsumer(Filename);
|
||||
std::string CoveragePath = getCoveragePath(Filename, MainFilename);
|
||||
std::unique_ptr<raw_ostream> CovStream;
|
||||
if (Options.NoOutput)
|
||||
if (Options.NoOutput || Options.Intermediate)
|
||||
CovStream = std::make_unique<raw_null_ostream>();
|
||||
else if (!Options.UseStdout)
|
||||
CovStream = openCoveragePath(CoveragePath);
|
||||
@ -723,6 +724,51 @@ void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename,
|
||||
source.coverage = FileCoverage;
|
||||
}
|
||||
|
||||
if (Options.Intermediate && !Options.NoOutput) {
|
||||
// gcov 7.* unexpectedly create multiple .gcov files, which was fixed in 8.0
|
||||
// (PR GCC/82702). We create just one file.
|
||||
std::string outputPath(sys::path::filename(MainFilename));
|
||||
std::error_code ec;
|
||||
raw_fd_ostream os(outputPath + ".gcov", ec, sys::fs::OF_Text);
|
||||
if (ec) {
|
||||
errs() << ec.message() << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
for (const SourceInfo &source : sources) {
|
||||
os << "file:" << source.filename << '\n';
|
||||
for (const GCOVFunction *f : source.functions)
|
||||
os << "function:" << f->startLine << ',' << f->getEntryCount() << ','
|
||||
<< f->Name << '\n';
|
||||
const LineData &line = LineInfo[source.filename];
|
||||
for (uint32_t lineNum = 0; lineNum != line.LastLine; ++lineNum) {
|
||||
BlockLines::const_iterator blocksIt = line.Blocks.find(lineNum);
|
||||
if (blocksIt == line.Blocks.end())
|
||||
continue;
|
||||
const BlockVector &blocks = blocksIt->second;
|
||||
// GCC 8 (r254259) added third third field for Ada:
|
||||
// lcount:<line>,<count>,<has_unexecuted_blocks>
|
||||
// We don't need the third field.
|
||||
os << "lcount:" << (lineNum + 1) << ','
|
||||
<< GCOVBlock::getLineCount(blocks) << '\n';
|
||||
|
||||
if (!Options.BranchInfo)
|
||||
continue;
|
||||
for (const GCOVBlock *block : blocks) {
|
||||
if (block->getLastLine() != lineNum + 1 ||
|
||||
block->getNumDstEdges() < 2)
|
||||
continue;
|
||||
for (const GCOVArc *arc : block->dsts()) {
|
||||
const char *type = block->getCount()
|
||||
? arc->Count ? "taken" : "nottaken"
|
||||
: "notexec";
|
||||
os << "branch:" << (lineNum + 1) << ',' << type << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Options.UseStdout) {
|
||||
// FIXME: There is no way to detect calls given current instrumentation.
|
||||
if (Options.FuncCoverage)
|
||||
@ -833,7 +879,7 @@ void FileInfo::printFileCoverage(raw_ostream &OS) const {
|
||||
const GCOVCoverage &Coverage = source.coverage;
|
||||
OS << "File '" << Coverage.Name << "'\n";
|
||||
printCoverage(OS, Coverage);
|
||||
if (!Options.NoOutput)
|
||||
if (!Options.NoOutput && !Options.Intermediate)
|
||||
OS << "Creating '" << source.name << "'\n";
|
||||
OS << "\n";
|
||||
}
|
||||
|
@ -19,10 +19,14 @@ int main() { // GCOV: 1: [[@LINE]]:int
|
||||
// RUN: cp %s %p/Inputs/gcov-8.gc* .
|
||||
|
||||
/// FIXME Lines executed:100.00% of 12
|
||||
// RUN: llvm-cov gcov gcov-8.c | FileCheck %s
|
||||
// CHECK: File 'gcov-8.c'
|
||||
// CHECK-NEXT: Lines executed:77.78% of 9
|
||||
// CHECK-NEXT: Creating 'gcov-8.c.gcov'
|
||||
// RUN: llvm-cov gcov gcov-8.c | FileCheck %s --check-prefixes=OUT,OUTFILE
|
||||
// OUT: File 'gcov-8.c'
|
||||
// OUT-NEXT: Lines executed:77.78% of 9
|
||||
// OUT-B-NEXT: Branches executed:85.71% of 14
|
||||
// OUT-B-NEXT: Taken at least once:42.86% of 14
|
||||
// OUT-B-NEXT: No calls
|
||||
// OUTFILE-NEXT: Creating 'gcov-8.c.gcov'
|
||||
// OUT-EMPTY:
|
||||
|
||||
// RUN: FileCheck --input-file=%t/gcov-8.c.gcov --check-prefix=HEADER %s
|
||||
// RUN: FileCheck --input-file=%t/gcov-8.c.gcov --check-prefix=GCOV %s
|
||||
@ -33,3 +37,37 @@ int main() { // GCOV: 1: [[@LINE]]:int
|
||||
// HEADER-NEXT: -: 0:Runs:1{{$}}
|
||||
// HEADER-NEXT: -: 0:Programs:1
|
||||
// HEADER-NEXT: -: 1:/// Test that llvm-cov
|
||||
|
||||
// RUN: llvm-cov gcov -i gcov-8.c | FileCheck %s --check-prefix=OUT
|
||||
// RUN: FileCheck %s --check-prefix=I < gcov-8.c.gcov
|
||||
// RUN: llvm-cov gcov --intermediate-format gcov-8.c
|
||||
// RUN: FileCheck %s --check-prefix=I < gcov-8.c.gcov
|
||||
|
||||
// RUN: llvm-cov gcov -i -b gcov-8.c | FileCheck %s --check-prefixes=OUT,OUT-B
|
||||
// RUN: FileCheck %s --check-prefixes=I,I-B < gcov-8.c.gcov
|
||||
|
||||
// I:file:gcov-8.c
|
||||
// I-NEXT:function:4,1,main
|
||||
// I-NEXT:lcount:4,1
|
||||
// I-NEXT:lcount:6,12
|
||||
// I-B-NEXT:branch:6,taken
|
||||
// I-B-NEXT:branch:6,nottaken
|
||||
// I-NEXT:lcount:7,11
|
||||
// I-B-NEXT:branch:7,taken
|
||||
// I-B-NEXT:branch:7,nottaken
|
||||
// I-NEXT:lcount:8,7
|
||||
// I-B-NEXT:branch:8,taken
|
||||
// I-B-NEXT:branch:8,nottaken
|
||||
// I-NEXT:lcount:9,11
|
||||
// I-NEXT:lcount:10,11
|
||||
// I-B-NEXT:branch:10,taken
|
||||
// I-B-NEXT:branch:10,nottaken
|
||||
// I-NEXT:lcount:11,11
|
||||
// I-B-NEXT:branch:11,taken
|
||||
// I-B-NEXT:branch:11,nottaken
|
||||
// I-B-NEXT:branch:11,taken
|
||||
// I-B-NEXT:branch:11,nottaken
|
||||
// I-NEXT:lcount:12,0
|
||||
// I-B-NEXT:branch:12,notexec
|
||||
// I-B-NEXT:branch:12,notexec
|
||||
// I-NEXT:lcount:14,0
|
||||
|
55
test/tools/llvm-cov/gcov-intermediate-format.test
Normal file
55
test/tools/llvm-cov/gcov-intermediate-format.test
Normal file
@ -0,0 +1,55 @@
|
||||
REQUIRES: shell
|
||||
|
||||
RUN: rm -rf %t && mkdir %t && cd %t
|
||||
RUN: cp %S/Inputs/test.gcno %S/Inputs/test.gcda .
|
||||
|
||||
RUN: llvm-cov gcov -i test.cpp 2> %t.err | FileCheck %s --check-prefixes=OUT
|
||||
RUN: FileCheck %s --check-prefix=I < test.cpp.gcov
|
||||
RUN: cp test.cpp.gcov saved.cpp.gcov
|
||||
|
||||
# -i does not read source files. No ENOENT diagnostic.
|
||||
RUN: count 0 < %t.err
|
||||
|
||||
# -n suppresses the .gcov output.
|
||||
RUN: llvm-cov gcov -i -n test. | FileCheck %s --check-prefixes=OUT
|
||||
RUN: not ls test..gcov
|
||||
|
||||
# The output filename is formed by appending ".gcov" to the specifiled filename.
|
||||
RUN: llvm-cov gcov -i test. | FileCheck %s --check-prefix=OUT
|
||||
RUN: cmp test..gcov saved.cpp.gcov
|
||||
|
||||
RUN: llvm-cov gcov -i -b test.cpp | FileCheck %s --check-prefixes=OUT,OUT-B
|
||||
RUN: FileCheck %s --check-prefixes=I,I-B --match-full-lines --strict-whitespace < test.cpp.gcov
|
||||
|
||||
# Many other options are ignored.
|
||||
RUN: rm -f test.cpp.gcov && llvm-cov gcov -i -a -c -l -p -u -x test.cpp
|
||||
RUN: cmp test.cpp.gcov saved.cpp.gcov
|
||||
|
||||
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
|
||||
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
|
||||
OUT-EMPTY:
|
||||
|
||||
I:file:test.cpp
|
||||
I:function:10,4294967296,_ZN1A1BEv
|
||||
I-NEXT:function:12,0,_Z7uselessv
|
||||
I-NEXT:function:14,0,_Z12more_uselessv
|
||||
I-NEXT:function:18,1,_Z3foov
|
||||
I-NEXT:function:23,0,_Z3barv
|
||||
I-NEXT:function:28,4,_Z6assignii
|
||||
I-NEXT:function:32,1,_Z15initialize_gridv
|
||||
I-NEXT:function:38,1,main
|
||||
I:lcount:10,4294967296
|
||||
I:lcount:33,3
|
||||
I-B-NEXT:branch:33,taken
|
||||
I-B-NEXT:branch:33,taken
|
||||
I:file:./test.h
|
||||
I-NEXT:function:2,1,_ZN1AC2Ev
|
||||
I-NEXT:lcount:2,1
|
@ -105,6 +105,16 @@ int gcovMain(int argc, const char *argv[]) {
|
||||
cl::desc("Show coverage for each function"));
|
||||
cl::alias FuncSummaryA("function-summaries", cl::aliasopt(FuncSummary));
|
||||
|
||||
// Supported by gcov 4.9~8. gcov 9 (GCC r265587) removed --intermediate-format
|
||||
// and -i was changed to mean --json-format. We consider this format still
|
||||
// useful and support -i.
|
||||
cl::opt<bool> Intermediate(
|
||||
"intermediate-format", cl::init(false),
|
||||
cl::desc("Output .gcov in intermediate text format"));
|
||||
cl::alias IntermediateA("i", cl::desc("Alias for --intermediate-format"),
|
||||
cl::Grouping, cl::NotHidden,
|
||||
cl::aliasopt(Intermediate));
|
||||
|
||||
cl::opt<bool> NoOutput("n", cl::Grouping, cl::init(false),
|
||||
cl::desc("Do not output any .gcov files"));
|
||||
cl::alias NoOutputA("no-output", cl::aliasopt(NoOutput));
|
||||
@ -144,8 +154,8 @@ int gcovMain(int argc, const char *argv[]) {
|
||||
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
|
||||
|
||||
GCOV::Options Options(AllBlocks, BranchProb, BranchCount, FuncSummary,
|
||||
PreservePaths, UncondBranch, LongNames, NoOutput,
|
||||
UseStdout, HashFilenames);
|
||||
PreservePaths, UncondBranch, Intermediate, LongNames,
|
||||
NoOutput, UseStdout, HashFilenames);
|
||||
|
||||
for (const auto &SourceFile : SourceFiles)
|
||||
reportCoverage(SourceFile, ObjectDir, InputGCNO, InputGCDA, DumpGCOV,
|
||||
|
Loading…
Reference in New Issue
Block a user