1 /*===- InstrProfilingMerge.c - Profile in-process Merging ---------------===*\ 2 |* 3 |* The LLVM Compiler Infrastructure 4 |* 5 |* This file is distributed under the University of Illinois Open Source 6 |* License. See LICENSE.TXT for details. 7 |* 8 |*===----------------------------------------------------------------------===* 9 |* This file defines the API needed for in-process merging of profile data 10 |* stored in memory buffer. 11 \*===---------------------------------------------------------------------===*/ 12 13 #include "InstrProfiling.h" 14 #include "InstrProfilingInternal.h" 15 #include "InstrProfilingUtil.h" 16 17 #define INSTR_PROF_VALUE_PROF_DATA 18 #include "InstrProfData.inc" 19 20 COMPILER_RT_WEAK void (*VPMergeHook)(ValueProfData *, 21 __llvm_profile_data *) = NULL; 22 23 /* Returns 1 if profile is not structurally compatible. */ 24 COMPILER_RT_VISIBILITY 25 int __llvm_profile_check_compatibility(const char *ProfileData, 26 uint64_t ProfileSize) { 27 /* Check profile header only for now */ 28 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 29 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 30 SrcDataStart = 31 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 32 SrcDataEnd = SrcDataStart + Header->DataSize; 33 34 /* Check the header first. */ 35 if (Header->Magic != __llvm_profile_get_magic() || 36 Header->Version != __llvm_profile_get_version() || 37 Header->DataSize != 38 __llvm_profile_get_data_size(__llvm_profile_begin_data(), 39 __llvm_profile_end_data()) || 40 Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() - 41 __llvm_profile_begin_counters()) || 42 Header->NamesSize != (uint64_t)(__llvm_profile_end_names() - 43 __llvm_profile_begin_names()) || 44 Header->ValueKindLast != IPVK_Last) 45 return 1; 46 47 if (ProfileSize < sizeof(__llvm_profile_header) + 48 Header->DataSize * sizeof(__llvm_profile_data) + 49 Header->NamesSize + Header->CountersSize + 50 Header->ValueDataSize) 51 return 1; 52 53 for (SrcData = SrcDataStart, 54 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(); 55 SrcData < SrcDataEnd; ++SrcData, ++DstData) { 56 if (SrcData->NameRef != DstData->NameRef || 57 SrcData->FuncHash != DstData->FuncHash || 58 SrcData->NumCounters != DstData->NumCounters) 59 return 1; 60 } 61 62 /* Matched! */ 63 return 0; 64 } 65 66 COMPILER_RT_VISIBILITY 67 void __llvm_profile_merge_from_buffer(const char *ProfileData, 68 uint64_t ProfileSize) { 69 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 70 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 71 uint64_t *SrcCountersStart; 72 const char *SrcNameStart; 73 ValueProfData *SrcValueProfDataStart, *SrcValueProfData; 74 75 SrcDataStart = 76 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 77 SrcDataEnd = SrcDataStart + Header->DataSize; 78 SrcCountersStart = (uint64_t *)SrcDataEnd; 79 SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize); 80 SrcValueProfDataStart = 81 (ValueProfData *)(SrcNameStart + Header->NamesSize + 82 __llvm_profile_get_num_padding_bytes( 83 Header->NamesSize)); 84 85 for (SrcData = SrcDataStart, 86 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(), 87 SrcValueProfData = SrcValueProfDataStart; 88 SrcData < SrcDataEnd; ++SrcData, ++DstData) { 89 uint64_t *SrcCounters; 90 uint64_t *DstCounters = (uint64_t *)DstData->CounterPtr; 91 unsigned I, NC, NVK = 0; 92 93 NC = SrcData->NumCounters; 94 SrcCounters = SrcCountersStart + 95 ((size_t)SrcData->CounterPtr - Header->CountersDelta) / 96 sizeof(uint64_t); 97 for (I = 0; I < NC; I++) 98 DstCounters[I] += SrcCounters[I]; 99 100 /* Now merge value profile data. */ 101 if (!VPMergeHook) 102 continue; 103 104 for (I = 0; I <= IPVK_Last; I++) 105 NVK += (SrcData->NumValueSites[I] != 0); 106 107 if (!NVK) 108 continue; 109 110 VPMergeHook(SrcValueProfData, DstData); 111 SrcValueProfData = (ValueProfData *)((char *)SrcValueProfData + 112 SrcValueProfData->TotalSize); 113 } 114 } 115