| 1 | /*===- InstrProfiling.c - Support library for PGO instrumentation ---------===*\ |
|---|---|
| 2 | |* |
| 3 | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | |* See https://llvm.org/LICENSE.txt for license information. |
| 5 | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | |* |
| 7 | \*===----------------------------------------------------------------------===*/ |
| 8 | |
| 9 | // Note: This is linked into the Darwin kernel, and must remain compatible |
| 10 | // with freestanding compilation. See `darwin_add_builtin_libraries`. |
| 11 | |
| 12 | #include <limits.h> |
| 13 | #include <stdio.h> |
| 14 | #include <stdlib.h> |
| 15 | #include <string.h> |
| 16 | |
| 17 | #include "InstrProfiling.h" |
| 18 | #include "InstrProfilingInternal.h" |
| 19 | |
| 20 | #define INSTR_PROF_VALUE_PROF_DATA |
| 21 | #include "profile/InstrProfData.inc" |
| 22 | |
| 23 | static uint32_t __llvm_profile_global_timestamp = 1; |
| 24 | |
| 25 | COMPILER_RT_VISIBILITY |
| 26 | void INSTR_PROF_PROFILE_SET_TIMESTAMP(uint64_t *Probe) { |
| 27 | if (*Probe == 0 || *Probe == (uint64_t)-1) |
| 28 | *Probe = __llvm_profile_global_timestamp++; |
| 29 | } |
| 30 | |
| 31 | COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) { |
| 32 | return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64) |
| 33 | : (INSTR_PROF_RAW_MAGIC_32); |
| 34 | } |
| 35 | |
| 36 | COMPILER_RT_VISIBILITY void __llvm_profile_set_dumped(void) { |
| 37 | lprofSetProfileDumped(1); |
| 38 | } |
| 39 | |
| 40 | /* Return the number of bytes needed to add to SizeInBytes to make it |
| 41 | * the result a multiple of 8. |
| 42 | */ |
| 43 | COMPILER_RT_VISIBILITY uint8_t |
| 44 | __llvm_profile_get_num_padding_bytes(uint64_t SizeInBytes) { |
| 45 | return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); |
| 46 | } |
| 47 | |
| 48 | COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_version(void) { |
| 49 | return INSTR_PROF_RAW_VERSION_VAR; |
| 50 | } |
| 51 | |
| 52 | COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) { |
| 53 | if (__llvm_profile_get_version() & VARIANT_MASK_TEMPORAL_PROF) |
| 54 | __llvm_profile_global_timestamp = 1; |
| 55 | |
| 56 | char *I = __llvm_profile_begin_counters(); |
| 57 | char *E = __llvm_profile_end_counters(); |
| 58 | |
| 59 | char ResetValue = |
| 60 | (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE) ? 0xFF : 0; |
| 61 | memset(s: I, c: ResetValue, n: E - I); |
| 62 | |
| 63 | I = __llvm_profile_begin_bitmap(); |
| 64 | E = __llvm_profile_end_bitmap(); |
| 65 | memset(s: I, c: 0x0, n: E - I); |
| 66 | |
| 67 | const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); |
| 68 | const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); |
| 69 | const __llvm_profile_data *DI; |
| 70 | for (DI = DataBegin; DI < DataEnd; ++DI) { |
| 71 | uint64_t CurrentVSiteCount = 0; |
| 72 | uint32_t VKI, i; |
| 73 | if (!DI->Values) |
| 74 | continue; |
| 75 | |
| 76 | ValueProfNode **ValueCounters = (ValueProfNode **)DI->Values; |
| 77 | |
| 78 | for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI) |
| 79 | CurrentVSiteCount += DI->NumValueSites[VKI]; |
| 80 | |
| 81 | for (i = 0; i < CurrentVSiteCount; ++i) { |
| 82 | ValueProfNode *CurrVNode = ValueCounters[i]; |
| 83 | |
| 84 | while (CurrVNode) { |
| 85 | CurrVNode->Count = 0; |
| 86 | CurrVNode = CurrVNode->Next; |
| 87 | } |
| 88 | } |
| 89 | } |
| 90 | lprofSetProfileDumped(0); |
| 91 | } |
| 92 |