int main(int argc, const char *argv[]) { unsigned S, NS = 10, V; const __llvm_profile_data *Data, *DataEnd; setFunctionPointers(); Data = __llvm_profile_begin_data(); DataEnd = __llvm_profile_end_data(); for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) { void *func = __llvm_get_function_addr(Data); if (func == caller_without_value_site1 || func == caller_without_value_site2 || func == callee1 || func == callee2 || func == main) continue; __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data, 0 /*IPVK_IndirectCallTarget */, 10); if (func == caller_with_value_site_never_called1 || func == caller_with_value_site_never_called2) continue; for (S = 0; S < NS; S++) { unsigned C; for (C = 0; C < S + 1; C++) { __llvm_profile_instrument_target((uint64_t)callee1Ptr, (void *)Data, S); if (C % 2 == 0) __llvm_profile_instrument_target((uint64_t)callee2Ptr, (void *)Data, S); } } } }
COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) { uint64_t *I = __llvm_profile_begin_counters(); uint64_t *E = __llvm_profile_end_counters(); memset(I, 0, sizeof(uint64_t) * (E - I)); const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const __llvm_profile_data *DI; for (DI = DataBegin; DI != DataEnd; ++DI) { uint64_t CurrentVSiteCount = 0; uint32_t VKI, i; if (!DI->Values) continue; ValueProfNode **ValueCounters = (ValueProfNode **)DI->Values; for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI) CurrentVSiteCount += DI->NumValueSites[VKI]; for (i = 0; i < CurrentVSiteCount; ++i) { ValueProfNode *CurrentVNode = ValueCounters[i]; while (CurrentVNode) { CurrentVNode->VData.Count = 0; CurrentVNode = CurrentVNode->Next; } } } }
COMPILER_RT_VISIBILITY uint64_t lprofGetLoadModuleSignature() { /* A very fast way to compute a module signature. */ uint64_t CounterSize = (uint64_t)(__llvm_profile_end_counters() - __llvm_profile_begin_counters()); uint64_t DataSize = __llvm_profile_get_data_size(__llvm_profile_begin_data(), __llvm_profile_end_data()); uint64_t NamesSize = (uint64_t)(__llvm_profile_end_names() - __llvm_profile_begin_names()); uint64_t NumVnodes = (uint64_t)(__llvm_profile_end_vnodes() - __llvm_profile_begin_vnodes()); const __llvm_profile_data *FirstD = __llvm_profile_begin_data(); return (NamesSize << 40) + (CounterSize << 30) + (DataSize << 20) + (NumVnodes << 10) + (DataSize > 0 ? FirstD->NameRef : 0); }
/* Returns 1 if profile is not structurally compatible. */ COMPILER_RT_VISIBILITY int __llvm_profile_check_compatibility(const char *ProfileData, uint64_t ProfileSize) { /* Check profile header only for now */ __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; SrcDataStart = (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); SrcDataEnd = SrcDataStart + Header->DataSize; if (ProfileSize < sizeof(__llvm_profile_header)) return 1; /* Check the header first. */ if (Header->Magic != __llvm_profile_get_magic() || Header->Version != __llvm_profile_get_version() || Header->DataSize != __llvm_profile_get_data_size(__llvm_profile_begin_data(), __llvm_profile_end_data()) || Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() - __llvm_profile_begin_counters()) || Header->NamesSize != (uint64_t)(__llvm_profile_end_names() - __llvm_profile_begin_names()) || Header->ValueKindLast != IPVK_Last) return 1; if (ProfileSize < sizeof(__llvm_profile_header) + Header->DataSize * sizeof(__llvm_profile_data) + Header->NamesSize + Header->CountersSize) return 1; for (SrcData = SrcDataStart, DstData = (__llvm_profile_data *)__llvm_profile_begin_data(); SrcData < SrcDataEnd; ++SrcData, ++DstData) { if (SrcData->NameRef != DstData->NameRef || SrcData->FuncHash != DstData->FuncHash || SrcData->NumCounters != DstData->NumCounters) return 1; } /* Matched! */ return 0; }
uint64_t __llvm_profile_get_size_for_buffer(void) { const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const uint64_t *CountersBegin = __llvm_profile_begin_counters(); const uint64_t *CountersEnd = __llvm_profile_end_counters(); const char *NamesBegin = __llvm_profile_begin_names(); const char *NamesEnd = __llvm_profile_end_names(); return __llvm_profile_get_size_for_buffer_internal( DataBegin, DataEnd, CountersBegin, CountersEnd, NamesBegin, NamesEnd); }
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer, void *WriterCtx, VPDataReaderType *VPDataReader) { /* Match logic in __llvm_profile_write_buffer(). */ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const uint64_t *CountersBegin = __llvm_profile_begin_counters(); const uint64_t *CountersEnd = __llvm_profile_end_counters(); const char *NamesBegin = __llvm_profile_begin_names(); const char *NamesEnd = __llvm_profile_end_names(); return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd, CountersBegin, CountersEnd, VPDataReader, NamesBegin, NamesEnd); }
COMPILER_RT_VISIBILITY void __llvm_profile_merge_from_buffer(const char *ProfileData, uint64_t ProfileSize) { __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; uint64_t *SrcCountersStart; const char *SrcNameStart; ValueProfData *SrcValueProfDataStart, *SrcValueProfData; SrcDataStart = (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); SrcDataEnd = SrcDataStart + Header->DataSize; SrcCountersStart = (uint64_t *)SrcDataEnd; SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize); SrcValueProfDataStart = (ValueProfData *)(SrcNameStart + Header->NamesSize + __llvm_profile_get_num_padding_bytes( Header->NamesSize)); for (SrcData = SrcDataStart, DstData = (__llvm_profile_data *)__llvm_profile_begin_data(), SrcValueProfData = SrcValueProfDataStart; SrcData < SrcDataEnd; ++SrcData, ++DstData) { uint64_t *SrcCounters; uint64_t *DstCounters = (uint64_t *)DstData->CounterPtr; unsigned I, NC, NVK = 0; NC = SrcData->NumCounters; SrcCounters = SrcCountersStart + ((size_t)SrcData->CounterPtr - Header->CountersDelta) / sizeof(uint64_t); for (I = 0; I < NC; I++) DstCounters[I] += SrcCounters[I]; /* Now merge value profile data. */ if (!VPMergeHook) continue; for (I = 0; I <= IPVK_Last; I++) NVK += (SrcData->NumValueSites[I] != 0); if (!NVK) continue; VPMergeHook(SrcValueProfData, DstData); SrcValueProfData = (ValueProfData *)((char *)SrcValueProfData + SrcValueProfData->TotalSize); } }
LLVM_LIBRARY_VISIBILITY int llvmWriteProfData(WriterCallback Writer, void *WriterCtx, const uint8_t *ValueDataBegin, const uint64_t ValueDataSize) { /* Match logic in __llvm_profile_write_buffer(). */ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const uint64_t *CountersBegin = __llvm_profile_begin_counters(); const uint64_t *CountersEnd = __llvm_profile_end_counters(); const char *NamesBegin = __llvm_profile_begin_names(); const char *NamesEnd = __llvm_profile_end_names(); return llvmWriteProfDataImpl(Writer, WriterCtx, DataBegin, DataEnd, CountersBegin, CountersEnd, ValueDataBegin, ValueDataSize, NamesBegin, NamesEnd); }
int __llvm_profile_write_buffer(char *Buffer) { /* Match logic in __llvm_profile_get_size_for_buffer(). * Match logic in __llvm_profile_write_file(). */ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const uint64_t *CountersBegin = __llvm_profile_begin_counters(); const uint64_t *CountersEnd = __llvm_profile_end_counters(); const char *NamesBegin = __llvm_profile_begin_names(); const char *NamesEnd = __llvm_profile_end_names(); return __llvm_profile_write_buffer_internal(Buffer, DataBegin, DataEnd, CountersBegin, CountersEnd, NamesBegin, NamesEnd); }
int main(int argc, const char *argv[]) { unsigned S, NS = 0, I, V, doInstrument = 1; const __llvm_profile_data *Data, *DataEnd; if (argc >= 2 && !strcmp(argv[1], "DO_NOT_INSTRUMENT")) doInstrument = 0; for (I = 0; I < 128; I++) { CallerInfos[I].CallerAddr = CallerAddrs[I]; CallerInfos[I].NS = I; } qsort(CallerInfos, sizeof(CallerInfos) / sizeof(CallerInfo), sizeof(CallerInfo), cmpaddr); /* We will synthesis value profile data for 128 callers functions declared. * The number of value sites for each caller function is recorded in * the NS field of the CallerInfo object. For each value site, the number of * callee values is determined by the site index (modulo 8). The frequency * of each callee target synthesized is equal to V + 1, in which V is the * index of the target value for the callsite. */ Data = __llvm_profile_begin_data(); DataEnd = __llvm_profile_end_data(); for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) { void *func = __llvm_get_function_addr(Data); CallerInfo Key, *Res; Key.CallerAddr = func; Res = (CallerInfo *) bsearch(&Key, CallerInfos, sizeof(CallerInfos) / sizeof(CallerInfo), sizeof(CallerInfo), cmpaddr); if (Res) { NS = Res->NS; __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data, 0 /*IPVK_IndirectCallTarget */, NS); if (!doInstrument) { continue; } for (S = 0; S < NS; S++) { for (V = 0; V < S % 8; V++) { unsigned C; for (C = 0; C < V + 1; C++) __llvm_profile_instrument_target((uint64_t)CalleeAddrs[V], (void *)Data, S); } } } } }
static int writeFile(FILE *File) { /* Match logic in __llvm_profile_write_buffer(). */ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); const uint64_t *CountersBegin = __llvm_profile_begin_counters(); const uint64_t *CountersEnd = __llvm_profile_end_counters(); const char *NamesBegin = __llvm_profile_begin_names(); const char *NamesEnd = __llvm_profile_end_names(); /* Calculate size of sections. */ const uint64_t DataSize = DataEnd - DataBegin; const uint64_t CountersSize = CountersEnd - CountersBegin; const uint64_t NamesSize = NamesEnd - NamesBegin; const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t); /* Enough zeroes for padding. */ const char Zeroes[sizeof(uint64_t)] = {0}; /* Create the header. */ uint64_t Header[PROFILE_HEADER_SIZE]; Header[0] = __llvm_profile_get_magic(); Header[1] = __llvm_profile_get_version(); Header[2] = DataSize; Header[3] = CountersSize; Header[4] = NamesSize; Header[5] = (uintptr_t)CountersBegin; Header[6] = (uintptr_t)NamesBegin; /* Write the data. */ #define CHECK_fwrite(Data, Size, Length, File) \ do { if (fwrite(Data, Size, Length, File) != Length) return -1; } while (0) CHECK_fwrite(Header, sizeof(uint64_t), PROFILE_HEADER_SIZE, File); CHECK_fwrite(DataBegin, sizeof(__llvm_profile_data), DataSize, File); CHECK_fwrite(CountersBegin, sizeof(uint64_t), CountersSize, File); CHECK_fwrite(NamesBegin, sizeof(char), NamesSize, File); CHECK_fwrite(Zeroes, sizeof(char), Padding, File); #undef CHECK_fwrite return 0; }
int main(int argc, const char *argv[]) { unsigned S, NS = 0, V, doInstrument = 1; const __llvm_profile_data *Data, *DataEnd; if (argc < 2) doInstrument = 0; qsort(CallerAddrs, sizeof(CallerAddrs) / sizeof(void *), sizeof(void *), cmpaddr); /* We will synthesis value profile data for 128 callers functions. * The number of * value sites. The number values for each value site * ranges from 0 to 8. */ Data = __llvm_profile_begin_data(); DataEnd = __llvm_profile_end_data(); for (; Data < DataEnd; Data = __llvm_profile_iterate_data(Data)) { void *func = __llvm_get_function_addr(Data); if (bsearch(&func, CallerAddrs, sizeof(CallerAddrs) / sizeof(void *), sizeof(void *), cmpaddr)) { __llvm_profile_set_num_value_sites((__llvm_profile_data *)Data, 0 /*IPVK_IndirectCallTarget */, NS); if (!doInstrument) { NS++; continue; } for (S = 0; S < NS; S++) { for (V = 0; V < S % 8; V++) { unsigned C; for (C = 0; C < V + 1; C++) __llvm_profile_instrument_target((uint64_t)CalleeAddrs[V], (void *)Data, S); } } NS++; } } }