Skip to content

Commit d13d207

Browse files
committed
Upgrade LLVM profiling runtime to version 9
Fixes #19
1 parent 695dbbb commit d13d207

18 files changed

+613
-218
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ minicov = "0.3"
5353
```
5454

5555
3. Before your program exits, call `minicov::capture_coverage` with a sink (such
56-
as `Vec<u8>`) and then dump its contents to a file with the `.profraw` extension:
56+
as `Vec<u8>`) and then dump its contents to a file with the `.profraw` extension:
5757

5858
```ignore
5959
fn main() {
@@ -75,7 +75,7 @@ Sinks must implement the `CoverageWriter` trait. If the default `alloc` feature
7575
is enabled then an implementation is provided for `Vec<u8>`.
7676

7777
4. Use a tool such as [grcov] or llvm-cov to generate a human-readable coverage
78-
report:
78+
report:
7979

8080
```sh
8181
grcov output.profraw -b ./target/debug/my_program -s . -t html -o cov_report

minicov/build.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ fn main() {
1111
cfg.flag("-fno-coverage-mapping");
1212
cfg.define("COMPILER_RT_HAS_ATOMICS", "1");
1313

14-
let mut sources = vec![
14+
let sources = vec![
1515
"c/InstrProfiling.c",
1616
"c/InstrProfilingBuffer.c",
1717
"c/InstrProfilingInternal.c",
1818
"c/InstrProfilingMerge.c",
19+
"c/InstrProfilingPlatformLinux.c",
20+
"c/InstrProfilingPlatformOther.c",
21+
"c/InstrProfilingPlatformWindows.c",
1922
"c/InstrProfilingWriter.c",
2023
"c/InstrProfilingValue.c",
2124
"c/InstrProfilingVersionVar.c",
@@ -24,9 +27,6 @@ fn main() {
2427
let target = env::var("TARGET").unwrap_or_default();
2528
if target.ends_with("-uefi") {
2629
cfg.define("MINICOV_UEFI", "1");
27-
sources.push("c/InstrProfilingPlatformWindows.c");
28-
} else {
29-
sources.push("c/InstrProfilingPlatformLinux.c");
3030
}
3131

3232
for source in &sources {

minicov/c/InstrProfiling.c

+19-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
#define INSTR_PROF_VALUE_PROF_DATA
1616
#include "profile/InstrProfData.inc"
1717

18+
static uint32_t __llvm_profile_global_timestamp = 1;
19+
20+
COMPILER_RT_VISIBILITY
21+
void INSTR_PROF_PROFILE_SET_TIMESTAMP(uint64_t *Probe) {
22+
if (*Probe == 0 || *Probe == (uint64_t)-1)
23+
*Probe = __llvm_profile_global_timestamp++;
24+
}
25+
1826
COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) {
1927
return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64)
2028
: (INSTR_PROF_RAW_MAGIC_32);
@@ -37,13 +45,20 @@ COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_version(void) {
3745
}
3846

3947
COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
48+
if (__llvm_profile_get_version() & VARIANT_MASK_TEMPORAL_PROF)
49+
__llvm_profile_global_timestamp = 1;
50+
4051
char *I = __llvm_profile_begin_counters();
4152
char *E = __llvm_profile_end_counters();
4253

4354
char ResetValue =
4455
(__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) ? 0xFF : 0;
4556
memset(I, ResetValue, E - I);
4657

58+
I = __llvm_profile_begin_bitmap();
59+
E = __llvm_profile_end_bitmap();
60+
memset(I, 0x0, E - I);
61+
4762
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
4863
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
4964
const __llvm_profile_data *DI;
@@ -59,11 +74,11 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
5974
CurrentVSiteCount += DI->NumValueSites[VKI];
6075

6176
for (i = 0; i < CurrentVSiteCount; ++i) {
62-
ValueProfNode *CurrentVNode = ValueCounters[i];
77+
ValueProfNode *CurrVNode = ValueCounters[i];
6378

64-
while (CurrentVNode) {
65-
CurrentVNode->Count = 0;
66-
CurrentVNode = CurrentVNode->Next;
79+
while (CurrVNode) {
80+
CurrVNode->Count = 0;
81+
CurrVNode = CurrVNode->Next;
6782
}
6883
}
6984
}

minicov/c/InstrProfiling.h

+36-59
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@
1111

1212
#include "InstrProfilingPort.h"
1313

14+
// Make sure __LLVM_INSTR_PROFILE_GENERATE is always defined before
15+
// including instr_prof_interface.h so the interface functions are
16+
// declared correctly for the runtime.
17+
// __LLVM_INSTR_PROFILE_GENERATE is always `#undef`ed after the header,
18+
// because compiler-rt does not support profiling the profiling runtime itself.
19+
#ifndef __LLVM_INSTR_PROFILE_GENERATE
20+
#define __LLVM_INSTR_PROFILE_GENERATE
21+
#endif
22+
#include "profile/instr_prof_interface.h"
23+
#undef __LLVM_INSTR_PROFILE_GENERATE
24+
1425
#define INSTR_PROF_VISIBILITY COMPILER_RT_VISIBILITY
1526
#include "profile/InstrProfData.inc"
1627

@@ -53,6 +64,12 @@ int __llvm_profile_is_continuous_mode_enabled(void);
5364
*/
5465
void __llvm_profile_enable_continuous_mode(void);
5566

67+
/*!
68+
* \brief Disable continuous mode.
69+
*
70+
*/
71+
void __llvm_profile_disable_continuous_mode(void);
72+
5673
/*!
5774
* \brief Set the page size.
5875
*
@@ -87,33 +104,29 @@ const char *__llvm_profile_begin_names(void);
87104
const char *__llvm_profile_end_names(void);
88105
char *__llvm_profile_begin_counters(void);
89106
char *__llvm_profile_end_counters(void);
107+
char *__llvm_profile_begin_bitmap(void);
108+
char *__llvm_profile_end_bitmap(void);
90109
ValueProfNode *__llvm_profile_begin_vnodes();
91110
ValueProfNode *__llvm_profile_end_vnodes();
92111
uint32_t *__llvm_profile_begin_orderfile();
93112

94-
/*!
95-
* \brief Clear profile counters to zero.
96-
*
97-
*/
98-
void __llvm_profile_reset_counters(void);
99-
100113
/*!
101114
* \brief Merge profile data from buffer.
102115
*
103-
* Read profile data form buffer \p Profile and merge with in-process profile
104-
* counters. The client is expected to have checked or already knows the profile
105-
* data in the buffer matches the in-process counter structure before calling
106-
* it. Returns 0 (success) if the profile data is valid. Upon reading
107-
* invalid/corrupted profile data, returns 1 (failure).
116+
* Read profile data from buffer \p Profile and merge with in-process profile
117+
* counters and bitmaps. The client is expected to have checked or already
118+
* know the profile data in the buffer matches the in-process counter
119+
* structure before calling it. Returns 0 (success) if the profile data is
120+
* valid. Upon reading invalid/corrupted profile data, returns 1 (failure).
108121
*/
109122
int __llvm_profile_merge_from_buffer(const char *Profile, uint64_t Size);
110123

111124
/*! \brief Check if profile in buffer matches the current binary.
112125
*
113126
* Returns 0 (success) if the profile data in buffer \p Profile with size
114127
* \p Size was generated by the same binary and therefore matches
115-
* structurally the in-process counters. If the profile data in buffer is
116-
* not compatible, the interface returns 1 (failure).
128+
* structurally the in-process counters and bitmaps. If the profile data in
129+
* buffer is not compatible, the interface returns 1 (failure).
117130
*/
118131
int __llvm_profile_check_compatibility(const char *Profile,
119132
uint64_t Size);
@@ -147,50 +160,6 @@ void __llvm_profile_instrument_target_value(uint64_t TargetValue, void *Data,
147160
int __llvm_profile_write_file(void);
148161

149162
int __llvm_orderfile_write_file(void);
150-
/*!
151-
* \brief this is a wrapper interface to \c __llvm_profile_write_file.
152-
* After this interface is invoked, an already dumped flag will be set
153-
* so that profile won't be dumped again during program exit.
154-
* Invocation of interface __llvm_profile_reset_counters will clear
155-
* the flag. This interface is designed to be used to collect profile
156-
* data from user selected hot regions. The use model is
157-
* __llvm_profile_reset_counters();
158-
* ... hot region 1
159-
* __llvm_profile_dump();
160-
* .. some other code
161-
* __llvm_profile_reset_counters();
162-
* ... hot region 2
163-
* __llvm_profile_dump();
164-
*
165-
* It is expected that on-line profile merging is on with \c %m specifier
166-
* used in profile filename . If merging is not turned on, user is expected
167-
* to invoke __llvm_profile_set_filename to specify different profile names
168-
* for different regions before dumping to avoid profile write clobbering.
169-
*/
170-
int __llvm_profile_dump(void);
171-
172-
int __llvm_orderfile_dump(void);
173-
174-
/*!
175-
* \brief Set the filename for writing instrumentation data.
176-
*
177-
* Sets the filename to be used for subsequent calls to
178-
* \a __llvm_profile_write_file().
179-
*
180-
* \c Name is not copied, so it must remain valid. Passing NULL resets the
181-
* filename logic to the default behaviour.
182-
*
183-
* Note: There may be multiple copies of the profile runtime (one for each
184-
* instrumented image/DSO). This API only modifies the filename within the
185-
* copy of the runtime available to the calling image.
186-
*
187-
* Warning: This is a no-op if continuous mode (\ref
188-
* __llvm_profile_is_continuous_mode_enabled) is on. The reason for this is
189-
* that in continuous mode, profile counters are mmap()'d to the profile at
190-
* program initialization time. Support for transferring the mmap'd profile
191-
* counts to a new file has not been implemented.
192-
*/
193-
void __llvm_profile_set_filename(const char *Name);
194163

195164
/*!
196165
* \brief Set the FILE object for writing instrumentation data. Return 0 if set
@@ -275,6 +244,13 @@ uint64_t __llvm_profile_get_num_counters(const char *Begin, const char *End);
275244
/*! \brief Get the size of the profile counters section in bytes. */
276245
uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End);
277246

247+
/*! \brief Get the number of bytes in the profile bitmap section. */
248+
uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
249+
const char *End);
250+
251+
/*! \brief Get the size of the profile name section in bytes. */
252+
uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End);
253+
278254
/* ! \brief Given the sizes of the data and counter information, return the
279255
* number of padding bytes before and after the counters, and after the names,
280256
* in the raw profile.
@@ -285,8 +261,9 @@ uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End);
285261
* needed to achieve that.
286262
*/
287263
void __llvm_profile_get_padding_sizes_for_counters(
288-
uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
289-
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
264+
uint64_t DataSize, uint64_t CountersSize, uint64_t NumBitmapBytes,
265+
uint64_t NamesSize, uint64_t *PaddingBytesBeforeCounters,
266+
uint64_t *PaddingBytesAfterCounters, uint64_t *PaddingBytesAfterBitmap,
290267
uint64_t *PaddingBytesAfterNames);
291268

292269
/*!

minicov/c/InstrProfilingBuffer.c

+42-12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ COMPILER_RT_VISIBILITY void __llvm_profile_enable_continuous_mode(void) {
3333
ContinuouslySyncProfile = 1;
3434
}
3535

36+
COMPILER_RT_VISIBILITY void __llvm_profile_disable_continuous_mode(void) {
37+
ContinuouslySyncProfile = 0;
38+
}
39+
3640
COMPILER_RT_VISIBILITY void __llvm_profile_set_page_size(unsigned PS) {
3741
PageSize = PS;
3842
}
@@ -43,11 +47,14 @@ uint64_t __llvm_profile_get_size_for_buffer(void) {
4347
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
4448
const char *CountersBegin = __llvm_profile_begin_counters();
4549
const char *CountersEnd = __llvm_profile_end_counters();
50+
const char *BitmapBegin = __llvm_profile_begin_bitmap();
51+
const char *BitmapEnd = __llvm_profile_end_bitmap();
4652
const char *NamesBegin = __llvm_profile_begin_names();
4753
const char *NamesEnd = __llvm_profile_end_names();
4854

4955
return __llvm_profile_get_size_for_buffer_internal(
50-
DataBegin, DataEnd, CountersBegin, CountersEnd, NamesBegin, NamesEnd);
56+
DataBegin, DataEnd, CountersBegin, CountersEnd, BitmapBegin, BitmapEnd,
57+
NamesBegin, NamesEnd);
5158
}
5259

5360
COMPILER_RT_VISIBILITY
@@ -83,6 +90,17 @@ uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End) {
8390
__llvm_profile_counter_entry_size();
8491
}
8592

93+
COMPILER_RT_VISIBILITY
94+
uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
95+
const char *End) {
96+
return (End - Begin);
97+
}
98+
99+
COMPILER_RT_VISIBILITY
100+
uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End) {
101+
return End - Begin;
102+
}
103+
86104
/// Calculate the number of padding bytes needed to add to \p Offset in order
87105
/// for (\p Offset + Padding) to be page-aligned.
88106
static uint64_t calculateBytesNeededToPageAlign(uint64_t Offset) {
@@ -102,12 +120,16 @@ static int needsCounterPadding(void) {
102120

103121
COMPILER_RT_VISIBILITY
104122
void __llvm_profile_get_padding_sizes_for_counters(
105-
uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
106-
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
123+
uint64_t DataSize, uint64_t CountersSize, uint64_t NumBitmapBytes,
124+
uint64_t NamesSize, uint64_t *PaddingBytesBeforeCounters,
125+
uint64_t *PaddingBytesAfterCounters, uint64_t *PaddingBytesAfterBitmapBytes,
107126
uint64_t *PaddingBytesAfterNames) {
108127
if (!needsCounterPadding()) {
109128
*PaddingBytesBeforeCounters = 0;
110-
*PaddingBytesAfterCounters = 0;
129+
*PaddingBytesAfterCounters =
130+
__llvm_profile_get_num_padding_bytes(CountersSize);
131+
*PaddingBytesAfterBitmapBytes =
132+
__llvm_profile_get_num_padding_bytes(NumBitmapBytes);
111133
*PaddingBytesAfterNames = __llvm_profile_get_num_padding_bytes(NamesSize);
112134
return;
113135
}
@@ -117,31 +139,37 @@ void __llvm_profile_get_padding_sizes_for_counters(
117139
*PaddingBytesBeforeCounters =
118140
calculateBytesNeededToPageAlign(sizeof(__llvm_profile_header) + DataSize);
119141
*PaddingBytesAfterCounters = calculateBytesNeededToPageAlign(CountersSize);
142+
*PaddingBytesAfterBitmapBytes =
143+
calculateBytesNeededToPageAlign(NumBitmapBytes);
120144
*PaddingBytesAfterNames = calculateBytesNeededToPageAlign(NamesSize);
121145
}
122146

123147
COMPILER_RT_VISIBILITY
124148
uint64_t __llvm_profile_get_size_for_buffer_internal(
125149
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
126-
const char *CountersBegin, const char *CountersEnd, const char *NamesBegin,
127-
const char *NamesEnd) {
150+
const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin,
151+
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd) {
128152
/* Match logic in __llvm_profile_write_buffer(). */
129153
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
130154
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
131155
uint64_t CountersSize =
132156
__llvm_profile_get_counters_size(CountersBegin, CountersEnd);
157+
const uint64_t NumBitmapBytes =
158+
__llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
133159

134160
/* Determine how much padding is needed before/after the counters and after
135161
* the names. */
136162
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
137-
PaddingBytesAfterNames;
163+
PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes;
138164
__llvm_profile_get_padding_sizes_for_counters(
139-
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
140-
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);
165+
DataSize, CountersSize, NumBitmapBytes, NamesSize,
166+
&PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
167+
&PaddingBytesAfterBitmapBytes, &PaddingBytesAfterNames);
141168

142169
return sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
143170
DataSize + PaddingBytesBeforeCounters + CountersSize +
144-
PaddingBytesAfterCounters + NamesSize + PaddingBytesAfterNames;
171+
PaddingBytesAfterCounters + NumBitmapBytes +
172+
PaddingBytesAfterBitmapBytes + NamesSize + PaddingBytesAfterNames;
145173
}
146174

147175
COMPILER_RT_VISIBILITY
@@ -159,9 +187,11 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
159187
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
160188
char *Buffer, const __llvm_profile_data *DataBegin,
161189
const __llvm_profile_data *DataEnd, const char *CountersBegin,
162-
const char *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
190+
const char *CountersEnd, const char *BitmapBegin, const char *BitmapEnd,
191+
const char *NamesBegin, const char *NamesEnd) {
163192
ProfDataWriter BufferWriter;
164193
initBufferWriter(&BufferWriter, Buffer);
165194
return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
166-
CountersEnd, 0, NamesBegin, NamesEnd, 0);
195+
CountersEnd, BitmapBegin, BitmapEnd, 0, NamesBegin,
196+
NamesEnd, 0);
167197
}

0 commit comments

Comments
 (0)