llvm.org GIT mirror llvm / 63d80be
Revert "[llvm-cov] Add support for exporting coverage data to JSON" This reverts commit r276813. The Windows bots are complaining about some of the filename regexes in the tests: http://bb.pgr.jp/builders/ninja-clang-i686-msc19-R/builds/5299 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@276816 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 4 years ago
17 changed file(s) with 4 addition(s) and 759 deletion(s). Raw diff Collapse all Expand all
2323 * :ref:`gcov `
2424 * :ref:`show `
2525 * :ref:`report `
26 * :ref:`export `
2726
2827 .. program:: llvm-cov gcov
2928
315314 It is an error to specify an architecture that is not included in the
316315 universal binary or to use an architecture that does not match a
317316 non-universal binary.
318
319 EXPORT COMMAND
320 --------------
321
322 SYNOPSIS
323 ^^^^^^^^
324
325 :program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN*
326
327 DESCRIPTION
328 ^^^^^^^^^^^
329
330 The :program:`llvm-cov export` command exports regions, functions, expansions,
331 and summaries of the coverage of a binary *BIN* using the profile data
332 *PROFILE* as JSON.
333
334 For information on compiling programs for coverage and generating profile data,
335 see :ref:`llvm-cov-show`.
336
337 OPTIONS
338 ^^^^^^^
339
340 .. option:: -arch=
341
342 If the covered binary is a universal binary, select the architecture to use.
343 It is an error to specify an architecture that is not included in the
344 universal binary or to use an architecture that does not match a
345 non-universal binary.
+0
-38
test/tools/llvm-cov/Inputs/binary-formats.canonical.json less more
None // Metadata section
1 // CHECK: {"version":"1.0.0","type":"llvm.coverage.json.export","data":[
2
3 // Open Export
4 // CHECK-SAME: {"object":"{{[^\"]+}}","files":[
5
6 // File Object
7 // CHECK-SAME: {"filename":"{{[^\"]+}}/binary-formats.c",
8 // CHECK-SAME: "segments":[
9 // CHECK-SAME: [4,40,100,1,1],[4,42,0,0,0]],
10 // CHECK-SAME: "expansions":[],
11
12 // Verify the Summary Section for the first file
13 // CHECK-SAME: "summary":{
14 // CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100,"noncode":0},
15 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
16 // CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}}
17
18 // Close Files Array
19 // CHECK-SAME: ],
20
21 // Functions List
22 // CHECK-SAME: "functions":[
23 // CHECK-SAME: {"name":"main","count":100,"regions":[
24 // CHECK-SAME: [4,40,4,42,100,0,0,0]
25 // CHECK-SAME: ],
26 // CHECK-SAME: "filenames":["{{[^\"]+}}/binary-formats.c"]
27 // CHECK-SAME: }],
28
29
30 // Full Export Summary
31 // CHECK-SAME: "totals":{
32 // CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100,"noncode":0},
33 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
34 // CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}
35
36 // Close the export object, data array, and root object
37 // CHECK-SAME: }]}
+0
-53
test/tools/llvm-cov/Inputs/highlightedRanges.json less more
None // Metadata section
1 // CHECK: {"version":"1.0.0","type":"llvm.coverage.json.export","data":[
2
3 // Open Export
4 // CHECK-SAME: {"object":"{{[^\"]+}}","files":[
5
6 // File Object
7 // CHECK-SAME: {"filename":"{{[^\"]+}}/showHighlightedRanges.cpp",
8 // CHECK-SAME: "segments":[
9 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
10 // CHECK-SAME: "expansions":[],
11
12 // Verify the Summary Section for the first file
13 // CHECK-SAME: "summary":{
14 // CHECK-SAME: "lines":{"count":40,"covered":26,"percent":65,"noncode":0},
15 // CHECK-SAME: "functions":{"count":4,"covered":4,"percent":100},
16 // CHECK-SAME: "regions":{"count":19,"covered":11,"notcovered":8,"percent":57}}}
17
18 // Close Files Array
19 // CHECK-SAME: ],
20
21 // Functions List
22 // CHECK-SAME: "functions":[
23 // CHECK-SAME: {"name":"_Z4funcv","count":1,"regions":[
24 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
25 // CHECK-SAME: ],
26 // CHECK-SAME: "filenames":["{{[^\"]+}}/showHighlightedRanges.cpp"]
27 // CHECK-SAME: }
28 // CHECK-SAME: {"name":"_Z5func2i","count":1,"regions":[
29 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
30 // CHECK-SAME: ],
31 // CHECK-SAME: "filenames":["{{[^\"]+}}/showHighlightedRanges.cpp"]
32 // CHECK-SAME: }
33 // CHECK-SAME: {"name":"_Z4testv","count":1,"regions":[
34 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
35 // CHECK-SAME: ],
36 // CHECK-SAME: "filenames":["{{[^\"]+}}/showHighlightedRanges.cpp"]
37 // CHECK-SAME: }
38 // CHECK-SAME: {"name":"main","count":1,"regions":[
39 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
40 // CHECK-SAME: ],
41 // CHECK-SAME: "filenames":["{{[^\"]+}}/showHighlightedRanges.cpp"]
42 // CHECK-SAME: }],
43
44
45 // Full Export Summary
46 // CHECK-SAME: "totals":{
47 // CHECK-SAME: "lines":{"count":40,"covered":26,"percent":65,"noncode":0},
48 // CHECK-SAME: "functions":{"count":4,"covered":4,"percent":100},
49 // CHECK-SAME: "regions":{"count":19,"covered":11,"notcovered":8,"percent":57}}
50
51 // Close the export object, data array, and root object
52 // CHECK-SAME: }]}
+0
-38
test/tools/llvm-cov/Inputs/lineExecutionCounts.json less more
None // Metadata section
1 // CHECK: {"version":"1.0.0","type":"llvm.coverage.json.export","data":[
2
3 // Open Export
4 // CHECK-SAME: {"object":"{{[^\"]+}}","files":[
5
6 // File Object
7 // CHECK-SAME: {"filename":"{{[^\"]+}}/showLineExecutionCounts.cpp",
8 // CHECK-SAME: "segments":[
9 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
10 // CHECK-SAME: "expansions":[],
11
12 // Verify the Summary Section for the first file
13 // CHECK-SAME: "summary":{
14 // CHECK-SAME: "lines":{"count":20,"covered":16,"percent":80,"noncode":0},
15 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
16 // CHECK-SAME: "regions":{"count":10,"covered":7,"notcovered":3,"percent":70}}}
17
18 // Close Files Array
19 // CHECK-SAME: ],
20
21 // Functions List
22 // CHECK-SAME: "functions":[
23 // CHECK-SAME: {"name":"main","count":161,"regions":[
24 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
25 // CHECK-SAME: ],
26 // CHECK-SAME: "filenames":["{{[^\"]+}}/showLineExecutionCounts.cpp"]
27 // CHECK-SAME: }],
28
29
30 // Full Export Summary
31 // CHECK-SAME: "totals":{
32 // CHECK-SAME: "lines":{"count":20,"covered":16,"percent":80,"noncode":0},
33 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
34 // CHECK-SAME: "regions":{"count":10,"covered":7,"notcovered":3,"percent":70}}
35
36 // Close the export object, data array, and root object
37 // CHECK-SAME: }]}
+0
-37
test/tools/llvm-cov/Inputs/regionMarkers.json less more
None // Metadata section
1 // CHECK: {"version":"1.0.0","type":"llvm.coverage.json.export","data":[
2
3 // Open Export
4 // CHECK-SAME: {"object":"{{[^\"]+}}","files":[
5
6 // File Object
7 // CHECK-SAME: {"filename":"{{[^\"]+}}/showRegionMarkers.cpp",
8 // CHECK-SAME: "segments":[
9 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
10 // CHECK-SAME: "expansions":[],
11
12 // Verify the Summary Section for the first file
13 // CHECK-SAME: "summary":{
14 // CHECK-SAME: "lines":{"count":21,"covered":17,"percent":80,"noncode":0},
15 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
16 // CHECK-SAME: "regions":{"count":10,"covered":7,"notcovered":3,"percent":70}}
17
18 // Close Files Array
19 // CHECK-SAME: ],
20
21 // Functions List
22 // CHECK-SAME: "functions":[
23 // CHECK-SAME: {"name":"main","count":1111000,"regions":[
24 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
25 // CHECK-SAME: ],
26 // CHECK-SAME: "filenames":["{{[^\"]+}}/showRegionMarkers.cpp"]
27 // CHECK-SAME: }],
28
29 // Full Export Summary
30 // CHECK-SAME: "totals":{
31 // CHECK-SAME: "lines":{"count":21,"covered":17,"percent":80,"noncode":0},
32 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
33 // CHECK-SAME: "regions":{"count":10,"covered":7,"notcovered":3,"percent":70}}
34
35 // Close the export object, data array, and root object
36 // CHECK-SAME: }]}
+0
-51
test/tools/llvm-cov/Inputs/showExpansions.json less more
None // Metadata section
1 // CHECK: {"version":"1.0.0","type":"llvm.coverage.json.export","data":[
2
3 // Open Export
4 // CHECK-SAME: {"object":"{{[^\"]+}}","files":[
5
6 // File Object
7 // CHECK-SAME: {"filename":"{{[^\"]+}}/showExpansions.cpp",
8 // CHECK-SAME: "segments":[
9 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
10 // CHECK-SAME: "expansions":[
11 // CHECK-SAME: {"source_region":[24,5,24,17,100,0,1,1],
12 // CHECK-SAME: "target_regions":[
13 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
14 // CHECK-SAME: ],
15
16 // Yes, 4 of the same filename in a row
17 // CHECK-SAME: "filenames":[
18 // CHECK-SAME: "{{[^\"]+}}/showExpansions.cpp","{{[^\"]+}}/showExpansions.cpp",
19 // CHECK-SAME: "{{[^\"]+}}/showExpansions.cpp","{{[^\"]+}}/showExpansions.cpp"]
20 // CHECK-SAME: }],
21
22 // Verify the Summary Section for the first file
23 // CHECK-SAME: "summary":{
24 // CHECK-SAME: "lines":{"count":17,"covered":15,"percent":88,"noncode":0},
25 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
26 // CHECK-SAME: "regions":{"count":13,"covered":12,"notcovered":1,"percent":92}}
27
28 // Close Files Array
29 // CHECK-SAME: ],
30
31 // Functions List
32 // CHECK-SAME: "functions":[
33 // CHECK-SAME: {"name":"main","count":1,"regions":[
34 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}
35 // CHECK-SAME: ],
36 // CHECK-SAME: "filenames":[
37 // CHECK-SAME: "{{[^\"]+}}/showExpansions.cpp",
38 // CHECK-SAME: "{{[^\"]+}}/showExpansions.cpp",
39 // CHECK-SAME: "{{[^\"]+}}/showExpansions.cpp",
40 // CHECK-SAME: "{{[^\"]+}}/showExpansions.cpp"]
41 // CHECK-SAME: }],
42
43 // Full Export Summary
44 // CHECK-SAME: "totals":{
45 // CHECK-SAME: "lines":{"count":17,"covered":15,"percent":88,"noncode":0},
46 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
47 // CHECK-SAME: "regions":{"count":13,"covered":12,"notcovered":1,"percent":92}}
48
49 // Close the export object, data array, and root object
50 // CHECK-SAME: }]}
+0
-36
test/tools/llvm-cov/Inputs/universal-binary.json less more
None // Metadata section
1 // CHECK: {"version":"1.0.0","type":"llvm.coverage.json.export","data":[
2
3 // Open Export
4 // CHECK-SAME: {"object":"{{[^\"]+}}","files":[
5
6 // File Object
7 // CHECK-SAME: {"filename":"{{[^\"]+}}/universal-binary.c",
8 // CHECK-SAME: "segments":[
9 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
10 // CHECK-SAME: "expansions":[],
11
12 // Verify the Summary Section for the first file
13 // CHECK-SAME: "summary":{
14 // CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100,"noncode":0},
15 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
16 // CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}}
17
18 // Close Files Array
19 // CHECK-SAME: ],
20
21 // Functions List
22 // CHECK-SAME: "functions":[
23 // CHECK-SAME: {"name":"main","count":100,"regions":[
24 // CHECK-SAME: {{(\[[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+,[0-9]+\],?)+}}],
25 // CHECK-SAME: "filenames":["{{[^\"]+}}/universal-binary.c"]
26 // CHECK-SAME: }],
27
28 // Full Export Summary
29 // CHECK-SAME: "totals":{
30 // CHECK-SAME: "lines":{"count":1,"covered":1,"percent":100,"noncode":0},
31 // CHECK-SAME: "functions":{"count":1,"covered":1,"percent":100},
32 // CHECK-SAME: "regions":{"count":1,"covered":1,"notcovered":0,"percent":100}
33
34 // Close the export object, data array, and root object
35 // CHECK-SAME: }]}
66 // RUN: llvm-cov show %S/Inputs/binary-formats.macho32l -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
77 // RUN: llvm-cov show %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
88 // RUN: llvm-cov show %S/Inputs/binary-formats.macho32b -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
9
10 // RUN: llvm-cov export %S/Inputs/binary-formats.macho32l -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json
11 // RUN: llvm-cov export %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json
12 // RUN: llvm-cov export %S/Inputs/binary-formats.macho32b -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json
2323 DO_SOMETHING(i); // CHECK-DAG: Expansion at line [[@LINE]], 5 -> 17
2424 return 0;
2525 }
26 // RUN: llvm-cov export %S/Inputs/showExpansions.covmapping -instr-profile %S/Inputs/showExpansions.profdata 2>&1 | FileCheck %S/Inputs/showExpansions.json
4242 func2(9);
4343 return 0;
4444 }
45 // RUN: llvm-cov export %S/Inputs/highlightedRanges.covmapping -instr-profile %S/Inputs/highlightedRanges.profdata 2>&1 | FileCheck %S/Inputs/highlightedRanges.json
6868 // HTML:
161
[[@LINE-44]]
}

                  
                
6969 // HTML-WHOLE-FILE:
[[@LINE-44]]
// after

                  
                
7070 // HTML-FILTER-NOT:
[[@LINE-45]]
// after

                  
                
71
72 // RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -name=main 2>/dev/null > %t.json
73 // FileCheck -input-file=%t.json %S/Inputs/lineExecutionCounts.json
74 // RUN: cat %t.json | %python -c 'import json, sys; json.loads(sys.stdin.read())'
2222 }
2323
2424 // RUN: llvm-cov show %S/Inputs/regionMarkers.covmapping -instr-profile %t.profdata -show-regions -dump -filename-equivalence %s 2>&1 | FileCheck %s
25
26 // RUN: llvm-cov export %S/Inputs/regionMarkers.covmapping -instr-profile %t.profdata 2>&1 | FileCheck %S/Inputs/regionMarkers.json
44
55 // RUN: llvm-profdata merge %S/Inputs/universal-binary.proftext -o %t.profdata
66 // RUN: llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch x86_64 | FileCheck %s
7 // RUN: llvm-cov export %S/Inputs/universal-binary -instr-profile %t.profdata -arch x86_64 2>&1 | FileCheck %S/Inputs/universal-binary.json
8
97
108 // RUN: not llvm-cov show %S/Inputs/universal-binary -instr-profile %t.profdata -filename-equivalence %s -arch i386 2>&1 | FileCheck --check-prefix=WRONG-ARCH %s
119 // WRONG-ARCH: Failed to load coverage
33 llvm-cov.cpp
44 gcov.cpp
55 CodeCoverage.cpp
6 CoverageExporterJson.cpp
76 CoverageFilters.cpp
87 CoverageReport.cpp
98 CoverageSummaryInfo.cpp
3737 using namespace llvm;
3838 using namespace coverage;
3939
40 void exportCoverageDataToJson(StringRef ObjectFilename,
41 const coverage::CoverageMapping &CoverageMapping,
42 raw_ostream &OS);
43
4440 namespace {
4541 /// \brief The implementation of the coverage tool.
4642 class CodeCoverageTool {
4945 /// \brief The show command.
5046 Show,
5147 /// \brief The report command.
52 Report,
53 /// \brief The export command.
54 Export
48 Report
5549 };
5650
5751 /// \brief Print the error message to the error output stream.
9892
9993 int report(int argc, const char **argv,
10094 CommandLineParserType commandLineParser);
101
102 int export_(int argc, const char **argv,
103 CommandLineParserType commandLineParser);
10495
10596 std::string ObjectFilename;
10697 CoverageViewOptions ViewOpts;
542533 return show(argc, argv, commandLineParser);
543534 case Report:
544535 return report(argc, argv, commandLineParser);
545 case Export:
546 return export_(argc, argv, commandLineParser);
547536 }
548537 return 0;
549538 }
704693 return 0;
705694 }
706695
707 int CodeCoverageTool::export_(int argc, const char **argv,
708 CommandLineParserType commandLineParser) {
709
710 auto Err = commandLineParser(argc, argv);
711 if (Err)
712 return Err;
713
714 auto Coverage = load();
715 if (!Coverage) {
716 error("Could not load coverage information");
717 return 1;
718 }
719
720 exportCoverageDataToJson(ObjectFilename, *Coverage.get(), outs());
721
722 return 0;
723 }
724
725696 int showMain(int argc, const char *argv[]) {
726697 CodeCoverageTool Tool;
727698 return Tool.run(CodeCoverageTool::Show, argc, argv);
731702 CodeCoverageTool Tool;
732703 return Tool.run(CodeCoverageTool::Report, argc, argv);
733704 }
734
735 int exportMain(int argc, const char *argv[]) {
736 CodeCoverageTool Tool;
737 return Tool.run(CodeCoverageTool::Export, argc, argv);
738 }
+0
-418
tools/llvm-cov/CoverageExporterJson.cpp less more
None //===- CoverageExporterJson.cpp - Code coverage export --------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements export of code coverage data to JSON.
10 //
11 //===----------------------------------------------------------------------===//
12
13 //===----------------------------------------------------------------------===//
14 //
15 // The json code coverage export follows the following format
16 // Root: dict => Root Element containing metadata
17 // -- Data: array => Homogeneous array of one or more export objects
18 // ---- Export: dict => Json representation of one CoverageMapping
19 // ------ Files: array => List of objects describing coverage for files
20 // -------- File: dict => Coverage for a single file
21 // ---------- Segments: array => List of Segments contained in the file
22 // ------------ Segment: dict => Describes a segment of the file with a counter
23 // ---------- Expansions: array => List of expansion records
24 // ------------ Expansion: dict => Object that descibes a single expansion
25 // -------------- CountedRegion: dict => The region to be expanded
26 // -------------- TargetRegions: array => List of Regions in the expansion
27 // ---------------- CountedRegion: dict => Single Region in the expansion
28 // ---------- Summary: dict => Object summarizing the coverage for this file
29 // ------------ LineCoverage: dict => Object summarizing line coverage
30 // ------------ FunctionCoverage: dict => Object summarizing function coverage
31 // ------------ RegionCoverage: dict => Object summarizing region coverage
32 // ------ Functions: array => List of objects describing coverage for functions
33 // -------- Function: dict => Coverage info for a single function
34 // ---------- Filenames: array => List of filenames that the function relates to
35 // ---- Summary: dict => Object summarizing the coverage for the entire binary
36 // ------ LineCoverage: dict => Object summarizing line coverage
37 // ------ FunctionCoverage: dict => Object summarizing function coverage
38 // ------ RegionCoverage: dict => Object summarizing region coverage
39 //
40 //===----------------------------------------------------------------------===//
41
42 #include "CoverageSummaryInfo.h"
43 #include "CoverageViewOptions.h"
44 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
45 #include
46
47 /// \brief Major version of the JSON Coverage Export Format.
48 #define LLVM_COVERAGE_EXPORT_JSON_MAJOR 1
49
50 /// \brief Minor version of the JSON Coverage Export Format.
51 #define LLVM_COVERAGE_EXPORT_JSON_MINOR 0
52
53 /// \brief Patch version of the JSON Coverage Export Format.
54 #define LLVM_COVERAGE_EXPORT_JSON_PATCH 0
55
56 /// \brief The semantic version combined as a string.
57 #define LLVM_COVERAGE_EXPORT_JSON_STR "1.0.0"
58
59 /// \brief Unique type identifier for JSON coverage export.
60 #define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export"
61
62 using namespace llvm;
63 using namespace coverage;
64
65 class CoverageExporterJson {
66 /// \brief A Name of the object file coverage is for.
67 StringRef ObjectFilename;
68
69 /// \brief Output stream to print JSON to.
70 raw_ostream &OS;
71
72 /// \brief The full CoverageMapping object to export.
73 CoverageMapping Coverage;
74
75 /// \brief States that the JSON rendering machine can be in.
76 enum JsonState { None, NonEmptyElement, EmptyElement };
77
78 /// \brief Tracks state of the JSON output.
79 std::stack State;
80
81 /// \brief Get the object filename.
82 StringRef getObjectFilename() const { return ObjectFilename; }
83
84 /// \brief Emit a serialized scalar.
85 void emitSerialized(const int64_t Value) { OS << Value; }
86
87 /// \brief Emit a serialized string.
88 void emitSerialized(const std::string &Value) { OS << "\"" << Value << "\""; }
89
90 /// \brief Emit a comma if there is a previous element to delimit.
91 void emitComma() {
92 if (State.top() == JsonState::NonEmptyElement) {
93 OS << ",";
94 } else if (State.top() == JsonState::EmptyElement) {
95 State.pop();
96 assert((State.size() >= 1) && "Closed too many JSON elements");
97 State.push(JsonState::NonEmptyElement);
98 }
99 }
100
101 /// \brief Emit a starting dictionary/object character.
102 void emitDictStart() {
103 emitComma();
104 State.push(JsonState::EmptyElement);
105 OS << "{";
106 }
107
108 /// \brief Emit a dictionary/object key but no value.
109 void emitDictKey(const std::string &Key) {
110 emitComma();
111 OS << "\"" << Key << "\":";
112 State.pop();
113 assert((State.size() >= 1) && "Closed too many JSON elements");
114
115 // We do not want to emit a comma after this key.
116 State.push(JsonState::EmptyElement);
117 }
118
119 /// \brief Emit a dictionary/object key/value pair.
120 template
121 void emitDictElement(const std::string &Key, const V &Value) {
122 emitComma();
123 emitSerialized(Key);
124 OS << ":";
125 emitSerialized(Value);
126 }
127
128 /// \brief Emit a closing dictionary/object character.
129 void emitDictEnd() {
130 State.pop();
131 assert((State.size() >= 1) && "Closed too many JSON elements");
132 OS << "}";
133 }
134
135 /// \brief Emit a starting array character.
136 void emitArrayStart() {
137 emitComma();
138 State.push(JsonState::EmptyElement);
139 OS << "[";
140 }
141
142 /// \brief Emit an array element.
143 template void emitArrayElement(const V &Value) {
144 emitComma();
145 emitSerialized(Value);
146 }
147
148 /// \brief emit a closing array character.
149 void emitArrayEnd() {
150 State.pop();
151 assert((State.size() >= 1) && "Closed too many JSON elements");
152 OS << "]";
153 }
154
155 /// \brief Render the CoverageMapping object.
156 void renderRoot() {
157 // Start Root of JSON object.
158 emitDictStart();
159
160 emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
161 emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
162 emitDictKey("data");
163
164 // Start List of Exports.
165 emitArrayStart();
166
167 // Start Export.
168 emitDictStart();
169 emitDictElement("object", getObjectFilename());
170
171 emitDictKey("files");
172 FileCoverageSummary Totals = FileCoverageSummary("Totals");
173 renderFiles(Coverage.getUniqueSourceFiles(), Totals);
174
175 emitDictKey("functions");
176 renderFunctions(Coverage.getCoveredFunctions());
177
178 emitDictKey("totals");
179 renderSummary(Totals);
180
181 // End Export.
182 emitDictEnd();
183
184 // End List of Exports.
185 emitArrayEnd();
186
187 // End Root of JSON Object.
188 emitDictEnd();
189
190 assert((State.top() == JsonState::None) &&
191 "All Elements In JSON were Closed");
192 }
193
194 /// \brief Render an array of all the given functions.
195 void
196 renderFunctions(const iterator_range &Functions) {
197 // Start List of Functions.
198 emitArrayStart();
199
200 for (const auto &Function : Functions) {
201 // Start Function.
202 emitDictStart();
203
204 emitDictElement("name", Function.Name);
205 emitDictElement("count", Function.ExecutionCount);
206 emitDictKey("regions");
207
208 renderRegions(Function.CountedRegions);
209
210 emitDictKey("filenames");
211
212 // Start Filenames for Function.
213 emitArrayStart();
214
215 for (const auto &FileName : Function.Filenames)
216 emitArrayElement(FileName);
217
218 // End Filenames for Function.
219 emitArrayEnd();
220
221 // End Function.
222 emitDictEnd();
223 }
224
225 // End List of Functions.
226 emitArrayEnd();
227 }
228
229 /// \brief Render an array of all the source files, also pass back a Summary.
230 void renderFiles(ArrayRef SourceFiles,
231 FileCoverageSummary &Summary) {
232 // Start List of Files.
233 emitArrayStart();
234 for (const auto &SourceFile : SourceFiles) {
235 // Render the file.
236 auto FileCoverage = Coverage.getCoverageForFile(SourceFile);
237 renderFile(FileCoverage);
238
239 for (const auto &F : Coverage.getCoveredFunctions(SourceFile))
240 Summary.addFunction(FunctionCoverageSummary::get(F));
241 }
242
243 // End List of Files.
244 emitArrayEnd();
245 }
246
247 /// \brief Render a single file.
248 void renderFile(const CoverageData &FileCoverage) {
249 // Start File.
250 emitDictStart();
251
252 emitDictElement("filename", FileCoverage.getFilename());
253 emitDictKey("segments");
254
255 // Start List of Segments.
256 emitArrayStart();
257
258 for (const auto &Segment : FileCoverage)
259 renderSegment(Segment);
260
261 // End List of Segments.
262 emitArrayEnd();
263
264 emitDictKey("expansions");
265
266 // Start List of Expansions.
267 emitArrayStart();
268
269 for (const auto &Expansion : FileCoverage.getExpansions())
270 renderExpansion(Expansion);
271
272 // End List of Expansions.
273 emitArrayEnd();
274
275 FileCoverageSummary Summary =
276 FileCoverageSummary(FileCoverage.getFilename());
277 for (const auto &F :
278 Coverage.getCoveredFunctions(FileCoverage.getFilename()))
279 Summary.addFunction(FunctionCoverageSummary::get(F));
280
281 emitDictKey("summary");
282 renderSummary(Summary);
283
284 // End File.
285 emitDictEnd();
286 }
287
288 /// \brief Render a CoverageSegment.
289 void renderSegment(const CoverageSegment &Segment) {
290 // Start Segment.
291 emitArrayStart();
292
293 emitArrayElement(Segment.Line);
294 emitArrayElement(Segment.Col);
295 emitArrayElement(Segment.Count);
296 emitArrayElement(Segment.HasCount);
297 emitArrayElement(Segment.IsRegionEntry);
298
299 // End Segment.
300 emitArrayEnd();
301 }
302
303 /// \brief Render an ExpansionRecord.
304 void renderExpansion(const ExpansionRecord &Expansion) {
305 // Start Expansion.
306 emitDictStart();
307
308 // Mark the beginning and end of this expansion in the source file.
309 emitDictKey("source_region");
310 renderRegion(Expansion.Region);
311
312 // Enumerate the coverage information for the expansion.
313 emitDictKey("target_regions");
314 renderRegions(Expansion.Function.CountedRegions);
315
316 emitDictKey("filenames");
317 // Start List of Filenames to map the fileIDs.
318 emitArrayStart();
319 for (const auto &Filename : Expansion.Function.Filenames)
320 emitArrayElement(Filename);
321 // End List of Filenames.
322 emitArrayEnd();
323
324 // End Expansion.
325 emitDictEnd();
326 }
327
328 /// \brief Render a list of CountedRegions.
329 void renderRegions(ArrayRef Regions) {
330 // Start List of Regions.
331 emitArrayStart();
332
333 for (const auto &Region : Regions)
334 renderRegion(Region);
335
336 // End List of Regions.
337 emitArrayEnd();
338 }
339
340 /// \brief Render a single CountedRegion.
341 void renderRegion(const CountedRegion &Region) {
342 // Start CountedRegion.
343 emitArrayStart();
344
345 emitArrayElement(Region.LineStart);
346 emitArrayElement(Region.ColumnStart);
347 emitArrayElement(Region.LineEnd);
348 emitArrayElement(Region.ColumnEnd);
349 emitArrayElement(Region.ExecutionCount);
350 emitArrayElement(Region.FileID);
351 emitArrayElement(Region.ExpandedFileID);
352 emitArrayElement(Region.Kind);
353
354 // End CountedRegion.
355 emitArrayEnd();
356 }
357
358 /// \brief Render a FileCoverageSummary.
359 void renderSummary(const FileCoverageSummary &Summary) {
360 // Start Summary for the file.
361 emitDictStart();
362
363 emitDictKey("lines");
364
365 // Start Line Coverage Summary.
366 emitDictStart();
367 emitDictElement("count", Summary.LineCoverage.NumLines);
368 emitDictElement("covered", Summary.LineCoverage.Covered);
369 emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
370 emitDictElement("noncode", Summary.LineCoverage.NonCodeLines);
371 // End Line Coverage Summary.
372 emitDictEnd();
373
374 emitDictKey("functions");
375
376 // Start Function Coverage Summary.
377 emitDictStart();
378 emitDictElement("count", Summary.FunctionCoverage.NumFunctions);
379 emitDictElement("covered", Summary.FunctionCoverage.Executed);
380 emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
381 // End Function Coverage Summary.
382 emitDictEnd();
383
384 emitDictKey("regions");
385
386 // Start Region Coverage Summary.
387 emitDictStart();
388 emitDictElement("count", Summary.RegionCoverage.NumRegions);
389 emitDictElement("covered", Summary.RegionCoverage.Covered);
390 emitDictElement("notcovered", Summary.RegionCoverage.NotCovered);
391 emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
392 // End Region Coverage Summary.
393 emitDictEnd();
394
395 // End Summary for the file.
396 emitDictEnd();
397 }
398
399 public:
400 CoverageExporterJson(StringRef ObjectFilename,
401 const CoverageMapping &CoverageMapping, raw_ostream &OS)
402 : ObjectFilename(ObjectFilename), OS(OS), Coverage(CoverageMapping) {
403 State.push(JsonState::None);
404 }
405
406 /// \brief Print the CoverageMapping.
407 void print() { renderRoot(); }
408 };
409
410 /// \brief Export the given CoverageMapping to a JSON Format.
411 void exportCoverageDataToJson(StringRef ObjectFilename,
412 const CoverageMapping &CoverageMapping,
413 raw_ostream &OS) {
414 auto Exporter = CoverageExporterJson(ObjectFilename, CoverageMapping, OS);
415
416 Exporter.print();
417 }
2929 /// \brief The main entry point for the 'report' subcommand.
3030 int reportMain(int argc, const char *argv[]);
3131
32 /// \brief The main entry point for the 'export' subcommand.
33 int exportMain(int argc, const char *argv[]);
34
3532 /// \brief The main entry point for the 'convert-for-testing' subcommand.
3633 int convertForTestingMain(int argc, const char *argv[]);
3734
4037
4138 /// \brief Top level help.
4239 static int helpMain(int argc, const char *argv[]) {
43 errs() << "Usage: llvm-cov {export|gcov|report|show} [OPTION]...\n\n"
40 errs() << "Usage: llvm-cov {gcov|report|show} [OPTION]...\n\n"
4441 << "Shows code coverage information.\n\n"
4542 << "Subcommands:\n"
46 << " export: Export instrprof file to structured format.\n"
4743 << " gcov: Work with the gcov format.\n"
48 << " report: Summarize instrprof style coverage information.\n"
49 << " show: Annotate source files using instrprof style coverage.\n";
50
44 << " show: Annotate source files using instrprof style coverage.\n"
45 << " report: Summarize instrprof style coverage information.\n";
5146 return 0;
5247 }
5348
7267 typedef int (*MainFunction)(int, const char *[]);
7368 MainFunction Func = StringSwitch(argv[1])
7469 .Case("convert-for-testing", convertForTestingMain)
75 .Case("export", exportMain)
7670 .Case("gcov", gcovMain)
7771 .Case("report", reportMain)
7872 .Case("show", showMain)