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