-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add support for -fcoverage-mapping support #24160
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
Merged
sbc100
merged 32 commits into
emscripten-core:main
from
arsnyder16:arsnyder16-fcoverage
Jun 16, 2025
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
2aa40c7
Add initial support -fcoverage-mapping support
sbc100 959ea3f
Merge remote-tracking branch 'origin/main' into arsnyder16-fcoverage
arsnyder16 cf07e7e
update
arsnyder16 69756f8
updates
arsnyder16 af4b5dd
bitmaps
arsnyder16 12d5e88
update
arsnyder16 29ac528
Merge remote-tracking branch 'origin/main' into arsnyder16-fcoverage
arsnyder16 a0f30c6
update port
arsnyder16 90db882
fix incldue
arsnyder16 8207cb1
update
arsnyder16 57521f8
non rt
arsnyder16 eb7de01
Merge remote-tracking branch 'origin/main' into arsnyder16-fcoverage
arsnyder16 e1a9928
test
arsnyder16 10bbd61
move to compiler-rt
arsnyder16 94c4160
Merge branch 'main' into arsnyder16-fcoverage
arsnyder16 1621863
Merge remote-tracking branch 'origin/main' into arsnyder16-fcoverage
arsnyder16 bd84202
Merge branch 'arsnyder16-fcoverage' of https://github.com/arsnyder16/…
arsnyder16 afa9822
based on llvm path
arsnyder16 56a1d3a
fix
arsnyder16 36bcfaa
reduce diff
arsnyder16 b082a31
Merge branch 'main' into arsnyder16-fcoverage
arsnyder16 addc50d
Merge branch 'main' into arsnyder16-fcoverage
arsnyder16 6863798
test updates
arsnyder16 936ea91
Merge branch 'arsnyder16-fcoverage' of https://github.com/arsnyder16/…
arsnyder16 4c2bc02
debug
arsnyder16 4b3b892
Merge branch 'main' into arsnyder16-fcoverage
arsnyder16 ba2c163
Merge remote-tracking branch 'origin/main' into arsnyder16-fcoverage
arsnyder16 1509b0b
Merge branch 'arsnyder16-fcoverage' of https://github.com/arsnyder16/…
arsnyder16 d4fa36a
remove
arsnyder16 f31fb36
ignore on a few unsupported scenarios
arsnyder16 8f540e9
feedback
arsnyder16 fa5c99e
add flag and PR
arsnyder16 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1,023 changes: 1,023 additions & 0 deletions
1,023
system/lib/compiler-rt/include/profile/InstrProfData.inc
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/*===-- MemEntryDef.inc - MemProf profiling runtime macros -*- C++ -*-======== *\ | ||
|* | ||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
|* See https://llvm.org/LICENSE.txt for license information. | ||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|* | ||
\*===----------------------------------------------------------------------===*/ | ||
/* | ||
* This file defines the macros for memprof profiling data structures. | ||
* Eg. usage to define the memprof meminfoblock struct: | ||
* | ||
* struct MemInfoBlock { | ||
* #define MIBEntryDef(NameTag, Name, Type) Type Name; | ||
* #include MIBEntryDef.inc | ||
* #undef MIBEntryDef | ||
* }; | ||
* | ||
* This file has two identical copies. The primary copy lives in LLVM and | ||
* the other one sits in compiler-rt/include/profile directory. To make changes | ||
* in this file, first modify the primary copy and copy it over to compiler-rt. | ||
* Testing of any change in this file can start only after the two copies are | ||
* synced up. | ||
* | ||
\*===----------------------------------------------------------------------===*/ | ||
#ifndef MIBEntryDef | ||
#define MIBEntryDef(NameTag, Name, Type) | ||
#endif | ||
|
||
MIBEntryDef(AllocCount = 1, AllocCount, uint32_t) | ||
MIBEntryDef(TotalAccessCount = 2, TotalAccessCount, uint64_t) | ||
MIBEntryDef(MinAccessCount = 3, MinAccessCount, uint64_t) | ||
MIBEntryDef(MaxAccessCount = 4, MaxAccessCount, uint64_t) | ||
MIBEntryDef(TotalSize = 5, TotalSize, uint64_t) | ||
MIBEntryDef(MinSize = 6, MinSize, uint32_t) | ||
MIBEntryDef(MaxSize = 7, MaxSize, uint32_t) | ||
MIBEntryDef(AllocTimestamp = 8, AllocTimestamp, uint32_t) | ||
MIBEntryDef(DeallocTimestamp = 9, DeallocTimestamp, uint32_t) | ||
MIBEntryDef(TotalLifetime = 10, TotalLifetime, uint64_t) | ||
MIBEntryDef(MinLifetime = 11, MinLifetime, uint32_t) | ||
MIBEntryDef(MaxLifetime = 12, MaxLifetime, uint32_t) | ||
MIBEntryDef(AllocCpuId = 13, AllocCpuId, uint32_t) | ||
MIBEntryDef(DeallocCpuId = 14, DeallocCpuId, uint32_t) | ||
MIBEntryDef(NumMigratedCpu = 15, NumMigratedCpu, uint32_t) | ||
MIBEntryDef(NumLifetimeOverlaps = 16, NumLifetimeOverlaps, uint32_t) | ||
MIBEntryDef(NumSameAllocCpu = 17, NumSameAllocCpu, uint32_t) | ||
MIBEntryDef(NumSameDeallocCpu = 18, NumSameDeallocCpu, uint32_t) | ||
MIBEntryDef(DataTypeId = 19, DataTypeId, uint64_t) | ||
MIBEntryDef(TotalAccessDensity = 20, TotalAccessDensity, uint64_t) | ||
MIBEntryDef(MinAccessDensity = 21, MinAccessDensity, uint32_t) | ||
MIBEntryDef(MaxAccessDensity = 22, MaxAccessDensity, uint32_t) | ||
MIBEntryDef(TotalLifetimeAccessDensity = 23, TotalLifetimeAccessDensity, uint64_t) | ||
MIBEntryDef(MinLifetimeAccessDensity = 24, MinLifetimeAccessDensity, uint32_t) | ||
MIBEntryDef(MaxLifetimeAccessDensity = 25, MaxLifetimeAccessDensity, uint32_t) | ||
MIBEntryDef(AccessHistogramSize = 26, AccessHistogramSize, uint32_t) | ||
MIBEntryDef(AccessHistogram = 27, AccessHistogram, uintptr_t) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
#ifndef MEMPROF_DATA_INC | ||
#define MEMPROF_DATA_INC | ||
/*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\ | ||
|* | ||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
|* See https://llvm.org/LICENSE.txt for license information. | ||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|* | ||
\*===----------------------------------------------------------------------===*/ | ||
/* | ||
* This is the main file that defines all the data structure, signature, | ||
* constant literals that are shared across profiling runtime library, | ||
* and host tools (reader/writer). | ||
* | ||
* This file has two identical copies. The primary copy lives in LLVM and | ||
* the other one sits in compiler-rt/include/profile directory. To make changes | ||
* in this file, first modify the primary copy and copy it over to compiler-rt. | ||
* Testing of any change in this file can start only after the two copies are | ||
* synced up. | ||
* | ||
\*===----------------------------------------------------------------------===*/ | ||
#include <string.h> | ||
|
||
#ifdef _MSC_VER | ||
#define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop)) | ||
#else | ||
#define PACKED(...) __VA_ARGS__ __attribute__((__packed__)) | ||
#endif | ||
|
||
// A 64-bit magic number to uniquely identify the raw binary memprof profile file. | ||
#define MEMPROF_RAW_MAGIC_64 \ | ||
((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \ | ||
(uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129) | ||
|
||
// The version number of the raw binary format. | ||
#define MEMPROF_RAW_VERSION 4ULL | ||
|
||
// Currently supported versions. | ||
#define MEMPROF_RAW_SUPPORTED_VERSIONS \ | ||
{ 3ULL, 4ULL } | ||
|
||
#define MEMPROF_V3_MIB_SIZE 132ULL; | ||
|
||
#define MEMPROF_BUILDID_MAX_SIZE 32ULL | ||
|
||
namespace llvm { | ||
namespace memprof { | ||
// A struct describing the header used for the raw binary memprof profile format. | ||
PACKED(struct Header { | ||
uint64_t Magic; | ||
uint64_t Version; | ||
uint64_t TotalSize; | ||
uint64_t SegmentOffset; | ||
uint64_t MIBOffset; | ||
uint64_t StackOffset; | ||
}); | ||
|
||
// A struct describing the information necessary to describe a /proc/maps | ||
// segment entry for a particular binary/library identified by its build id. | ||
PACKED(struct SegmentEntry { | ||
uint64_t Start; | ||
uint64_t End; | ||
uint64_t Offset; | ||
uint64_t BuildIdSize; | ||
uint8_t BuildId[MEMPROF_BUILDID_MAX_SIZE] = {0}; | ||
|
||
// This constructor is only used in tests so don't set the BuildId. | ||
SegmentEntry(uint64_t S, uint64_t E, uint64_t O) | ||
: Start(S), End(E), Offset(O), BuildIdSize(0) {} | ||
|
||
SegmentEntry(const SegmentEntry& S) { | ||
Start = S.Start; | ||
End = S.End; | ||
Offset = S.Offset; | ||
BuildIdSize = S.BuildIdSize; | ||
memcpy(BuildId, S.BuildId, S.BuildIdSize); | ||
} | ||
|
||
SegmentEntry& operator=(const SegmentEntry& S) { | ||
Start = S.Start; | ||
End = S.End; | ||
Offset = S.Offset; | ||
BuildIdSize = S.BuildIdSize; | ||
memcpy(BuildId, S.BuildId, S.BuildIdSize); | ||
return *this; | ||
} | ||
|
||
bool operator==(const SegmentEntry& S) const { | ||
return Start == S.Start && End == S.End && Offset == S.Offset && | ||
BuildIdSize == S.BuildIdSize && | ||
memcmp(BuildId, S.BuildId, S.BuildIdSize) == 0; | ||
} | ||
}); | ||
|
||
// Packed struct definition for MSVC. We can't use the PACKED macro defined in | ||
// MemProfData.inc since it would mean we are embedding a directive (the | ||
// #include for MIBEntryDef) into the macros which is undefined behaviour. | ||
#ifdef _MSC_VER | ||
__pragma(pack(push,1)) | ||
#endif | ||
|
||
// A struct representing the heap allocation characteristics of a particular | ||
// runtime context. This struct is shared between the compiler-rt runtime and | ||
// the raw profile reader. The indexed format uses a separate, self-describing | ||
// backwards compatible format. | ||
struct MemInfoBlock{ | ||
|
||
#define MIBEntryDef(NameTag, Name, Type) Type Name; | ||
#include "MIBEntryDef.inc" | ||
#undef MIBEntryDef | ||
|
||
bool operator==(const MemInfoBlock& Other) const { | ||
bool IsEqual = true; | ||
#define MIBEntryDef(NameTag, Name, Type) \ | ||
IsEqual = (IsEqual && Name == Other.Name); | ||
#include "MIBEntryDef.inc" | ||
#undef MIBEntryDef | ||
return IsEqual; | ||
} | ||
|
||
MemInfoBlock() { | ||
#define MIBEntryDef(NameTag, Name, Type) Name = Type(); | ||
#include "MIBEntryDef.inc" | ||
#undef MIBEntryDef | ||
} | ||
|
||
MemInfoBlock(uint32_t Size, uint64_t AccessCount, uint32_t AllocTs, | ||
uint32_t DeallocTs, uint32_t AllocCpu, uint32_t DeallocCpu, | ||
uintptr_t Histogram, uint32_t HistogramSize) | ||
: MemInfoBlock() { | ||
AllocCount = 1U; | ||
TotalAccessCount = AccessCount; | ||
MinAccessCount = AccessCount; | ||
MaxAccessCount = AccessCount; | ||
TotalSize = Size; | ||
MinSize = Size; | ||
MaxSize = Size; | ||
AllocTimestamp = AllocTs; | ||
DeallocTimestamp = DeallocTs; | ||
TotalLifetime = DeallocTimestamp - AllocTimestamp; | ||
MinLifetime = TotalLifetime; | ||
MaxLifetime = TotalLifetime; | ||
// Access density is accesses per byte. Multiply by 100 to include the | ||
// fractional part. | ||
TotalAccessDensity = AccessCount * 100 / Size; | ||
MinAccessDensity = TotalAccessDensity; | ||
MaxAccessDensity = TotalAccessDensity; | ||
// Lifetime access density is the access density per second of lifetime. | ||
// Multiply by 1000 to convert denominator lifetime to seconds (using a | ||
// minimum lifetime of 1ms to avoid divide by 0. Do the multiplication first | ||
// to reduce truncations to 0. | ||
TotalLifetimeAccessDensity = | ||
TotalAccessDensity * 1000 / (TotalLifetime ? TotalLifetime : 1); | ||
MinLifetimeAccessDensity = TotalLifetimeAccessDensity; | ||
MaxLifetimeAccessDensity = TotalLifetimeAccessDensity; | ||
AllocCpuId = AllocCpu; | ||
DeallocCpuId = DeallocCpu; | ||
NumMigratedCpu = AllocCpuId != DeallocCpuId; | ||
AccessHistogramSize = HistogramSize; | ||
AccessHistogram = Histogram; | ||
} | ||
|
||
void Merge(const MemInfoBlock &newMIB) { | ||
AllocCount += newMIB.AllocCount; | ||
|
||
TotalAccessCount += newMIB.TotalAccessCount; | ||
MinAccessCount = newMIB.MinAccessCount < MinAccessCount ? newMIB.MinAccessCount : MinAccessCount; | ||
MaxAccessCount = newMIB.MaxAccessCount > MaxAccessCount ? newMIB.MaxAccessCount : MaxAccessCount; | ||
|
||
TotalSize += newMIB.TotalSize; | ||
MinSize = newMIB.MinSize < MinSize ? newMIB.MinSize : MinSize; | ||
MaxSize = newMIB.MaxSize > MaxSize ? newMIB.MaxSize : MaxSize; | ||
|
||
TotalLifetime += newMIB.TotalLifetime; | ||
MinLifetime = newMIB.MinLifetime < MinLifetime ? newMIB.MinLifetime : MinLifetime; | ||
MaxLifetime = newMIB.MaxLifetime > MaxLifetime ? newMIB.MaxLifetime : MaxLifetime; | ||
|
||
TotalAccessDensity += newMIB.TotalAccessDensity; | ||
MinAccessDensity = newMIB.MinAccessDensity < MinAccessDensity | ||
? newMIB.MinAccessDensity | ||
: MinAccessDensity; | ||
MaxAccessDensity = newMIB.MaxAccessDensity > MaxAccessDensity | ||
? newMIB.MaxAccessDensity | ||
: MaxAccessDensity; | ||
|
||
TotalLifetimeAccessDensity += newMIB.TotalLifetimeAccessDensity; | ||
MinLifetimeAccessDensity = | ||
newMIB.MinLifetimeAccessDensity < MinLifetimeAccessDensity | ||
? newMIB.MinLifetimeAccessDensity | ||
: MinLifetimeAccessDensity; | ||
MaxLifetimeAccessDensity = | ||
newMIB.MaxLifetimeAccessDensity > MaxLifetimeAccessDensity | ||
? newMIB.MaxLifetimeAccessDensity | ||
: MaxLifetimeAccessDensity; | ||
|
||
// We know newMIB was deallocated later, so just need to check if it was | ||
// allocated before last one deallocated. | ||
NumLifetimeOverlaps += newMIB.AllocTimestamp < DeallocTimestamp; | ||
AllocTimestamp = newMIB.AllocTimestamp; | ||
DeallocTimestamp = newMIB.DeallocTimestamp; | ||
|
||
NumSameAllocCpu += AllocCpuId == newMIB.AllocCpuId; | ||
NumSameDeallocCpu += DeallocCpuId == newMIB.DeallocCpuId; | ||
AllocCpuId = newMIB.AllocCpuId; | ||
DeallocCpuId = newMIB.DeallocCpuId; | ||
|
||
// For merging histograms, we always keep the longer histogram, and add | ||
// values of shorter histogram to larger one. | ||
uintptr_t ShorterHistogram; | ||
uint32_t ShorterHistogramSize; | ||
if (newMIB.AccessHistogramSize > AccessHistogramSize) { | ||
ShorterHistogram = AccessHistogram; | ||
ShorterHistogramSize = AccessHistogramSize; | ||
// Swap histogram of current to larger histogram | ||
AccessHistogram = newMIB.AccessHistogram; | ||
AccessHistogramSize = newMIB.AccessHistogramSize; | ||
} else { | ||
ShorterHistogram = newMIB.AccessHistogram; | ||
ShorterHistogramSize = newMIB.AccessHistogramSize; | ||
} | ||
for (size_t i = 0; i < ShorterHistogramSize; ++i) { | ||
((uint64_t *)AccessHistogram)[i] += ((uint64_t *)ShorterHistogram)[i]; | ||
} | ||
} | ||
|
||
#ifdef _MSC_VER | ||
} __pragma(pack(pop)); | ||
#else | ||
} __attribute__((__packed__)); | ||
#endif | ||
|
||
} // namespace memprof | ||
} // namespace llvm | ||
|
||
#endif |
92 changes: 92 additions & 0 deletions
92
system/lib/compiler-rt/include/profile/instr_prof_interface.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/*===---- instr_prof_interface.h - Instrumentation PGO User Program API ----=== | ||
* | ||
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
* See https://llvm.org/LICENSE.txt for license information. | ||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
* | ||
*===-----------------------------------------------------------------------=== | ||
* | ||
* This header provides a public interface for fine-grained control of counter | ||
* reset and profile dumping. These interface functions can be directly called | ||
* in user programs. | ||
* | ||
\*===---------------------------------------------------------------------===*/ | ||
|
||
#ifndef COMPILER_RT_INSTR_PROFILING | ||
#define COMPILER_RT_INSTR_PROFILING | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifdef __LLVM_INSTR_PROFILE_GENERATE | ||
// Profile file reset and dump interfaces. | ||
// When `-fprofile[-instr]-generate`/`-fcs-profile-generate` is in effect, | ||
// clang defines __LLVM_INSTR_PROFILE_GENERATE to pick up the API calls. | ||
|
||
/*! | ||
* \brief Set the filename for writing instrumentation data. | ||
* | ||
* Sets the filename to be used for subsequent calls to | ||
* \a __llvm_profile_write_file(). | ||
* | ||
* \c Name is not copied, so it must remain valid. Passing NULL resets the | ||
* filename logic to the default behaviour. | ||
* | ||
* Note: There may be multiple copies of the profile runtime (one for each | ||
* instrumented image/DSO). This API only modifies the filename within the | ||
* copy of the runtime available to the calling image. | ||
* | ||
* Warning: This is a no-op if continuous mode (\ref | ||
* __llvm_profile_is_continuous_mode_enabled) is on. The reason for this is | ||
* that in continuous mode, profile counters are mmap()'d to the profile at | ||
* program initialization time. Support for transferring the mmap'd profile | ||
* counts to a new file has not been implemented. | ||
*/ | ||
void __llvm_profile_set_filename(const char *Name); | ||
|
||
/*! | ||
* \brief Interface to set all PGO counters to zero for the current process. | ||
* | ||
*/ | ||
void __llvm_profile_reset_counters(void); | ||
|
||
/*! | ||
* \brief this is a wrapper interface to \c __llvm_profile_write_file. | ||
* After this interface is invoked, an already dumped flag will be set | ||
* so that profile won't be dumped again during program exit. | ||
* Invocation of interface __llvm_profile_reset_counters will clear | ||
* the flag. This interface is designed to be used to collect profile | ||
* data from user selected hot regions. The use model is | ||
* __llvm_profile_reset_counters(); | ||
* ... hot region 1 | ||
* __llvm_profile_dump(); | ||
* .. some other code | ||
* __llvm_profile_reset_counters(); | ||
* ... hot region 2 | ||
* __llvm_profile_dump(); | ||
* | ||
* It is expected that on-line profile merging is on with \c %m specifier | ||
* used in profile filename . If merging is not turned on, user is expected | ||
* to invoke __llvm_profile_set_filename to specify different profile names | ||
* for different regions before dumping to avoid profile write clobbering. | ||
*/ | ||
int __llvm_profile_dump(void); | ||
|
||
// Interface to dump the current process' order file to disk. | ||
int __llvm_orderfile_dump(void); | ||
|
||
#else | ||
|
||
#define __llvm_profile_set_filename(Name) | ||
#define __llvm_profile_reset_counters() | ||
#define __llvm_profile_dump() (0) | ||
#define __llvm_orderfile_dump() (0) | ||
|
||
#endif | ||
|
||
#ifdef __cplusplus | ||
} // extern "C" | ||
#endif | ||
|
||
#endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.