KallistiOS
git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
gcov.h
Go to the documentation of this file.
1
/* KallistiOS ##version##
2
3
kos/gcov.h
4
Copyright (C) 2026 Andress Barajas
5
6
*/
7
8
/** \file kos/gcov.h
9
\brief Code-coverage (.gcda) output on top of GCC's libgcov.
10
\ingroup gcov
11
12
Writes GCC coverage (.gcda) files on a KOS target. The coverage *runtime* is
13
the toolchain's own libgcov; this addon supplies the file I/O that GCC's
14
freestanding libgcov leaves to the platform. Build with --coverage and
15
kos-cc wires everything up; coverage is flushed automatically at exit.
16
17
\author Andress Barajas
18
*/
19
20
#ifndef __KOS_GCOV_H
21
#define __KOS_GCOV_H
22
23
#include <sys/cdefs.h>
24
__BEGIN_DECLS
25
26
/** \defgroup gcov GCOV
27
\brief GCOV coverage and PGO support for KOS
28
\ingroup debugging
29
30
This file provides runtime support for GCOV, a coverage analysis tool built
31
into GCC. GCOV allows you to determine which parts of your code were executed,
32
how often, and which branches were taken. This is especially helpful for
33
analyzing test coverage or identifying unused code paths.
34
35
GCOV's runtime instrumentation writes `.gcda` files that serve two workflows
36
here, both from a plain `--coverage` build:
37
38
1. Code coverage -- which lines/branches ran, for gcov/lcov reports.
39
2. Arc-based PGO -- recompile with `-fprofile-use` and the compiler
40
optimizes from the edge counts (block layout, inlining, branch
41
prediction, function reordering).
42
43
What is NOT available is value-profiling PGO (`-fprofile-generate` /
44
`-fprofile-values`). GCC's freestanding libgcov for these targets ships no
45
value profilers, so those builds fail to link.
46
47
Compile-time flag:
48
49
- `--coverage`: shorthand for `-fprofile-arcs -ftest-coverage`. Instruments
50
edges so per-function execution counts are written to `.gcda` at runtime.
51
Also emits `.gcno` notes that map counters back to source lines and branches;
52
required for human-readable coverage reports.
53
54
When optimizing with `-fprofile-use` (step 4), these companion flags help:
55
56
- `-fprofile-correction`: counter updates are non-atomic by default, so a
57
multi-threaded run (KOS is threaded) can record an inconsistent profile;
58
without this, `-fprofile-use` errors out. This smooths such
59
inconsistencies with heuristics instead.
60
61
- `-fprofile-partial-training`: by default `-fprofile-use` treats any
62
function not seen during the run as cold and optimizes it for size. A
63
single console run rarely exercises everything, so this tells the compiler
64
to optimize un-exercised functions normally rather than pessimizing them.
65
66
- `-fprofile-update=atomic`: (generate side) make counter updates atomic so a
67
threaded run yields an exact, consistent profile, at some runtime cost --
68
an alternative to `-fprofile-correction`.
69
70
See the GCC manual's "Instrumentation Options" and "Optimize Options" for the
71
authoritative descriptions of every flag above.
72
73
Collecting, Analyzing, and Optimizing:
74
75
1. **Compile with coverage support:**
76
77
```sh
78
CFLAGS += --coverage
79
```
80
81
This generates `.gcno` files alongside your object files.
82
83
2. **Run your program on hardware:**
84
85
Counts accumulate in memory as the program runs. Getting them out:
86
87
- If your program returns from `main()` (or calls `exit()`), the data is
88
flushed automatically -- this addon registers an `atexit()` handler --
89
so you need not do anything.
90
91
- If your program never exits (an infinite main loop, as many console
92
programs have), that handler never runs. Call `kos_gcov_dump()`
93
yourself to write the data.
94
95
By default each `.gcda` is written at its full build-time path under
96
`/pc` (Ex. /opt/toolchains/dc/kos/examples/dreamcast/profiling/gcov/gcov.gcda),
97
so it matches the source it was generated from. Override the prefix from your
98
program with `setenv(GCOV_PREFIX, "/your/path", 1)` before the data is dumped,
99
and/or set `GCOV_PREFIX_STRIP` to drop leading path components.
100
101
3. **Generate an HTML report with LCOV:**
102
103
Use this Makefile target to capture and visualize results:
104
105
```make
106
lcov:
107
lcov \
108
--gcov-tool=$(KOS_GCOV) \
109
--directory . \
110
--base-directory . \
111
--capture \
112
--rc geninfo_unexecuted_blocks=1 \
113
--ignore-errors inconsistent,unused,source,empty \
114
--output-file coverage.info
115
genhtml coverage.info --output-directory html \
116
--ignore-errors inconsistent,source
117
open html/index.html
118
```
119
120
The extra flags keep lcov 2.x (current Homebrew/distro versions, much
121
stricter than 1.x) from aborting on coverage-data quirks that are normal
122
for optimized and inlined/header code.
123
124
This generates a full HTML report with annotated source code in the
125
`html/` directory.
126
127
4. **(Optional) Optimize with the profile (PGO):**
128
129
Recompile the same sources with `-fprofile-use` plus the companion flags
130
above (`-fprofile-correction` is required -- KOS is threaded):
131
132
```sh
133
CFLAGS += -fprofile-use -fprofile-correction -fprofile-partial-training
134
```
135
136
`-fprofile-use` reads each object's `.gcda` from the build tree (where
137
step 2 wrote it) and optimizes from the edge counts.
138
139
@{
140
*/
141
142
/** \brief Environment variable to set the output directory for `.gcda` files.
143
\ingroup gcov
144
145
If set, this value is prepended to the stripped source path to form the
146
final output path.
147
*/
148
#define GCOV_PREFIX "GCOV_PREFIX"
149
150
/** \brief Environment variable to control path stripping.
151
\ingroup gcov
152
153
Number of leading directory components removed from the build-time source
154
path before GCOV_PREFIX is applied.
155
*/
156
#define GCOV_PREFIX_STRIP "GCOV_PREFIX_STRIP"
157
158
/** \brief Write coverage data for every instrumented object.
159
160
Flushes the current in-memory counters to `.gcda` on disk (under GCOV_PREFIX
161
/ GCOV_PREFIX_STRIP).
162
163
You normally do NOT need to call this: when a program returns from main()
164
or calls exit(), this addon's atexit handler flushes the data for you. Call
165
it explicitly only when that shutdown path never runs -- most commonly a
166
program with an infinite main loop that never returns.
167
168
\note Existing .gcda files are overwritten, not merged.
169
*/
170
void
kos_gcov_dump
(
void
);
171
172
/** @} */
173
174
__END_DECLS
175
176
#endif
/* __KOS_GCOV_H */
kos_gcov_dump
void kos_gcov_dump(void)
Write coverage data for every instrumented object.
addons
include
kos
gcov.h
Generated by
1.12.0