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 return 1; 51 52 for (SrcData = SrcDataStart, 53 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(); 54 SrcData < SrcDataEnd; ++SrcData, ++DstData) { 55 if (SrcData->NameRef != DstData->NameRef || 56 SrcData->FuncHash != DstData->FuncHash || 57 SrcData->NumCounters != DstData->NumCounters) 58 return 1; 59 } 60 61 /* Matched! */ 62 return 0; 63 } 64 65 COMPILER_RT_VISIBILITY 66 void __llvm_profile_merge_from_buffer(const char *ProfileData, 67 uint64_t ProfileSize) { 68 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 69 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 70 uint64_t *SrcCountersStart; 71 const char *SrcNameStart; 72 ValueProfData *SrcValueProfDataStart, *SrcValueProfData; 73 74 SrcDataStart = 75 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 76 SrcDataEnd = SrcDataStart + Header->DataSize; 77 SrcCountersStart = (uint64_t *)SrcDataEnd; 78 SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize); 79 SrcValueProfDataStart = 80 (ValueProfData *)(SrcNameStart + Header->NamesSize + 81 __llvm_profile_get_num_padding_bytes( 82 Header->NamesSize)); 83 84 for (SrcData = SrcDataStart, 85 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(), 86 SrcValueProfData = SrcValueProfDataStart; 87 SrcData < SrcDataEnd; ++SrcData, ++DstData) { 88 uint64_t *SrcCounters; 89 uint64_t *DstCounters = (uint64_t *)DstData->CounterPtr; 90 unsigned I, NC, NVK = 0; 91 92 NC = SrcData->NumCounters; 93 SrcCounters = SrcCountersStart + 94 ((size_t)SrcData->CounterPtr - Header->CountersDelta) / 95 sizeof(uint64_t); 96 for (I = 0; I < NC; I++) 97 DstCounters[I] += SrcCounters[I]; 98 99 /* Now merge value profile data. */ 100 if (!VPMergeHook) 101 continue; 102 103 for (I = 0; I <= IPVK_Last; I++) 104 NVK += (SrcData->NumValueSites[I] != 0); 105 106 if (!NVK) 107 continue; 108 109 VPMergeHook(SrcValueProfData, DstData); 110 SrcValueProfData = (ValueProfData *)((char *)SrcValueProfData + 111 SrcValueProfData->TotalSize); 112 } 113 } 114