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