|  | /*===- InstrProfilingMerge.c - Profile in-process Merging  ---------------===*\ | 
|  | |* | 
|  | |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | |* See https://llvm.org/LICENSE.txt for license information. | 
|  | |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | |* | 
|  | |*===----------------------------------------------------------------------===* | 
|  | |* This file defines the API needed for in-process merging of profile data | 
|  | |* stored in memory buffer. | 
|  | \*===---------------------------------------------------------------------===*/ | 
|  |  | 
|  | #include "InstrProfiling.h" | 
|  | #include "InstrProfilingInternal.h" | 
|  | #include "InstrProfilingUtil.h" | 
|  |  | 
|  | #define INSTR_PROF_VALUE_PROF_DATA | 
|  | #include "profile/InstrProfData.inc" | 
|  |  | 
|  | COMPILER_RT_VISIBILITY | 
|  | void (*VPMergeHook)(ValueProfData *, __llvm_profile_data *); | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | 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); | 
|  | } | 
|  | } |