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_VISIBILITY 21 void (*VPMergeHook)(ValueProfData *, __llvm_profile_data *); 22 23 COMPILER_RT_VISIBILITY 24 uint64_t lprofGetLoadModuleSignature() { 25 /* A very fast way to compute a module signature. */ 26 uint64_t CounterSize = (uint64_t)(__llvm_profile_end_counters() - 27 __llvm_profile_begin_counters()); 28 uint64_t DataSize = __llvm_profile_get_data_size(__llvm_profile_begin_data(), 29 __llvm_profile_end_data()); 30 uint64_t NamesSize = 31 (uint64_t)(__llvm_profile_end_names() - __llvm_profile_begin_names()); 32 uint64_t NumVnodes = 33 (uint64_t)(__llvm_profile_end_vnodes() - __llvm_profile_begin_vnodes()); 34 const __llvm_profile_data *FirstD = __llvm_profile_begin_data(); 35 36 return (NamesSize << 40) + (CounterSize << 30) + (DataSize << 20) + 37 (NumVnodes << 10) + (DataSize > 0 ? FirstD->NameRef : 0); 38 } 39 40 /* Returns 1 if profile is not structurally compatible. */ 41 COMPILER_RT_VISIBILITY 42 int __llvm_profile_check_compatibility(const char *ProfileData, 43 uint64_t ProfileSize) { 44 /* Check profile header only for now */ 45 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 46 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 47 SrcDataStart = 48 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 49 SrcDataEnd = SrcDataStart + Header->DataSize; 50 51 if (ProfileSize < sizeof(__llvm_profile_header)) 52 return 1; 53 54 /* Check the header first. */ 55 if (Header->Magic != __llvm_profile_get_magic() || 56 Header->Version != __llvm_profile_get_version() || 57 Header->DataSize != 58 __llvm_profile_get_data_size(__llvm_profile_begin_data(), 59 __llvm_profile_end_data()) || 60 Header->CountersSize != (uint64_t)(__llvm_profile_end_counters() - 61 __llvm_profile_begin_counters()) || 62 Header->NamesSize != (uint64_t)(__llvm_profile_end_names() - 63 __llvm_profile_begin_names()) || 64 Header->ValueKindLast != IPVK_Last) 65 return 1; 66 67 if (ProfileSize < sizeof(__llvm_profile_header) + 68 Header->DataSize * sizeof(__llvm_profile_data) + 69 Header->NamesSize + Header->CountersSize) 70 return 1; 71 72 for (SrcData = SrcDataStart, 73 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(); 74 SrcData < SrcDataEnd; ++SrcData, ++DstData) { 75 if (SrcData->NameRef != DstData->NameRef || 76 SrcData->FuncHash != DstData->FuncHash || 77 SrcData->NumCounters != DstData->NumCounters) 78 return 1; 79 } 80 81 /* Matched! */ 82 return 0; 83 } 84 85 COMPILER_RT_VISIBILITY 86 void __llvm_profile_merge_from_buffer(const char *ProfileData, 87 uint64_t ProfileSize) { 88 __llvm_profile_data *SrcDataStart, *SrcDataEnd, *SrcData, *DstData; 89 __llvm_profile_header *Header = (__llvm_profile_header *)ProfileData; 90 uint64_t *SrcCountersStart; 91 const char *SrcNameStart; 92 ValueProfData *SrcValueProfDataStart, *SrcValueProfData; 93 94 SrcDataStart = 95 (__llvm_profile_data *)(ProfileData + sizeof(__llvm_profile_header)); 96 SrcDataEnd = SrcDataStart + Header->DataSize; 97 SrcCountersStart = (uint64_t *)SrcDataEnd; 98 SrcNameStart = (const char *)(SrcCountersStart + Header->CountersSize); 99 SrcValueProfDataStart = 100 (ValueProfData *)(SrcNameStart + Header->NamesSize + 101 __llvm_profile_get_num_padding_bytes( 102 Header->NamesSize)); 103 104 for (SrcData = SrcDataStart, 105 DstData = (__llvm_profile_data *)__llvm_profile_begin_data(), 106 SrcValueProfData = SrcValueProfDataStart; 107 SrcData < SrcDataEnd; ++SrcData, ++DstData) { 108 uint64_t *SrcCounters; 109 uint64_t *DstCounters = (uint64_t *)DstData->CounterPtr; 110 unsigned I, NC, NVK = 0; 111 112 NC = SrcData->NumCounters; 113 SrcCounters = SrcCountersStart + 114 ((size_t)SrcData->CounterPtr - Header->CountersDelta) / 115 sizeof(uint64_t); 116 for (I = 0; I < NC; I++) 117 DstCounters[I] += SrcCounters[I]; 118 119 /* Now merge value profile data. */ 120 if (!VPMergeHook) 121 continue; 122 123 for (I = 0; I <= IPVK_Last; I++) 124 NVK += (SrcData->NumValueSites[I] != 0); 125 126 if (!NVK) 127 continue; 128 129 VPMergeHook(SrcValueProfData, DstData); 130 SrcValueProfData = (ValueProfData *)((char *)SrcValueProfData + 131 SrcValueProfData->TotalSize); 132 } 133 } 134