-
Notifications
You must be signed in to change notification settings - Fork 0
Support clang coverage profile 10, 9, 8 #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Right now clang versions 14-19 with profile version 8,9,10 are added. Clean master branch in x86 platform is not linkable with any version of clang. just compilable. Clean master branch in ARM platform is not compilable with any version of clang. Only in clang-19 if we disable this flag `-mgeneral-regs-only`it will succesfuly compile and link. We tested compilability of our patch in above senario and compiled with clang 14-19 in x86 and in ARM it compiled and linked with clang-19 in the described situation.
xen/common/coverage/llvm.c
Outdated
*/ | ||
int __llvm_profile_runtime; | ||
|
||
extern char __start___llvm_prf_data[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should char
be const struct llvm_profile_data
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are linker-defined symbols that mark section boundaries. The linker doesn't understand C types like struct llvm_profile_data, it only places symbols at memory addresses.
Using char* (which is 1 byte) makes pointer arithmetic straightforward since we are really just working with addresses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tricky thing here is it is an array not a pointer. So it sort of "allures" people to use __start___llvm_prf_data[i]
even though our patch currently does not.
In fact, in the Linux counterpart, we calculate "the number of elements" using
static inline unsigned long __llvm_prf_data_count(void)
{
return __llvm_prf_data_size() /
sizeof(__llvm_prf_data_start[0]);
}
I still think we should revert to the right type. Similar thing for cnts
which is 64 bit wide.
typedef __PTRDIFF_TYPE__ ptrdiff_t; | ||
typedef __UINTPTR_TYPE__ uintptr_t; | ||
typedef __INTPTR_TYPE__ intptr_t; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this signed type is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signed arithmetic avoids undefined or unexpected behavior
If uintptr_t
were used, the subtraction could result in an unsigned underflow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give an example how the underflow could happen?
My concern is this touches some file that many other components depend and can block our patch specifically for coverage. But if you can justify it well, go for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we need that for llvm_profile_data
https://github.com/llvm/llvm-project/blob/e21dc4bd5474d04b8e62d7331362edcc5648d7e5/compiler-rt/include/profile/InstrProfData.inc#L80
xen/common/coverage/llvm.c
Outdated
extern char __stop___llvm_prf_cnts[]; | ||
|
||
#define START_DATA ((const char *)__start___llvm_prf_data) | ||
#define END_DATA ((const char *)__stop___llvm_prf_data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing code uses void *
and maybe let's not touch that.
I guess this is one of reasons why git diff
gets confused and bloated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried void*
but in calculation of sections I faced issue so I could not get output with llvm-profdata merge
.
xen/common/coverage/llvm.c
Outdated
uint64_t binary_ids_size; | ||
uint64_t data_size; | ||
uint64_t padding_bytes_before_counters; | ||
uint64_t counter_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before this field gets renamed to "num_counters" it has always been called "counter*s*_size"? llvm/llvm-project@a6f33ad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In new version renamed to num_{counter, num_data}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, Saman. This version looks great. Please see my new comments. (I will follow up in some of old conversations in a bit)
xen/common/coverage/llvm.c
Outdated
#elif __clang_major__ == 18 | ||
#define LLVM_PROFILE_VERSION 9 | ||
#define LLVM_PROFILE_NUM_KINDS 2 | ||
#elif __clang_major__ >= 14 && __clang_major__ <= 17 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
- I think
&& __clang_major__ <= 17
is not needed - three lines above: if the rest of code is using
>= 18
let's maybe be consistent here
xen/common/coverage/llvm.c
Outdated
* __llvm_profile_runtime must be defined according to the docs at: | ||
* | ||
* https://clang.llvm.org/docs/SourceBasedCodeCoverage.html | ||
* https://clang.llvm.org/docs/SourceBasedCodeCoverage.html |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please avoid whitespace changes (even though we should blame upstream for inappropriate coding style and lack of code linting :))
- (intptr_t)START_COUNTERS) / sizeof(uint64_t), | ||
.padding_bytes_after_counters = 0, | ||
.names_size = (END_NAMES - START_NAMES) * sizeof(char), | ||
.counters_delta = (uintptr_t)START_COUNTERS - (uintptr_t)START_DATA, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also sprinkle ifdef's to this initialization list
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The num calculation is a bit defensive to me. Do you have evidence
.num_data = (END_DATA - START_DATA) / sizeof(struct llvm_profile_data),
.num_counters = (END_COUNTERS - START_COUNTERS) / sizeof(uint64_t),
won't work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also sprinkle ifdef's to this initialization
could you please explain more
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won't work?
The linker script does not guarantee the data section boundaries align to sizeof(struct llvm_profile_data)
Followed up in old conversations as well. Saman can you give @matthew-l-weber and me write access to this repo so we can also resolve/reopen conversations? Thanks |
I tried to fix what you have suggested. But maybe I couldn't see some comments (it become messy :)) |
#endif | ||
|
||
#define LLVM_PROFILE_VERSION 4 | ||
#if __clang_major__ >= 19 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to update the clang version conversation in the docs? https://github.com/enum-class/xen/blob/saman/docs/hypervisor-guide/code-coverage.rst#compiling-xen
#define LLVM_PROFILE_VERSION 8 | ||
#define LLVM_PROFILE_NUM_KINDS 2 | ||
#else | ||
#error "Unsupported Clang version" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add a subsection talking about the profile and challenges with keeping it matching newer tool revisions? Maybe links to LLVM/clang profile definition to understand what to update in Xen and then a link in the docs to this file?
https://github.com/enum-class/xen/blob/saman/docs/hypervisor-guide/code-coverage.rst#clang-coverage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely. Here are some links to consider:
- LLVM documentation on the format: https://llvm.org/docs/InstrProfileFormat.html
- The changes of header fields (addition, rename, semantic changes) in LLVM source code: https://github.com/llvm/llvm-project/blame/llvmorg-22-init/compiler-rt/include/profile/InstrProfData.inc#L154
- Our post asking for opinions about supporting multiple versions from LLVM side: https://discourse.llvm.org/t/supporting-multiple-llvm-profile-formats-at-once/88473
We will also put up some general guideline text on how to update it in the future.
If we're close, it would be nice to see the squashed commits into the single commit for the patch so we can review the commit description and additional details to add under a --- |
@matthew-l-weber Thanks for your suggestions! Saman is refining and testing his v2, focusing on removing unnecessary type changes as pointed out both internally and by Andrew Cooper. We are breaking down the patches into these parts:
We will let you know when the squashed commit with proper message becomes ready. Thanks! |
compiler-rt/include/profile/InstrProfData.inc
for each version.Example of coverage output on ARM:
cov.zip