]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/profile/InstrProfilingValue.c
Upgrade to Unbound 1.5.9.
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / profile / InstrProfilingValue.c
1 /*===- InstrProfilingValue.c - Support library for PGO instrumentation ----===*\
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
10 #include "InstrProfiling.h"
11 #include "InstrProfilingInternal.h"
12 #include <limits.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #define INSTR_PROF_VALUE_PROF_DATA
17 #define INSTR_PROF_COMMON_API_IMPL
18 #include "InstrProfData.inc"
19
20 #define PROF_OOM(Msg) PROF_ERR(Msg ":%s\n", "Out of memory");
21 #define PROF_OOM_RETURN(Msg)                                                   \
22   {                                                                            \
23     PROF_OOM(Msg)                                                              \
24     free(ValueDataArray);                                                      \
25     return NULL;                                                               \
26   }
27
28 #if COMPILER_RT_HAS_ATOMICS != 1
29 COMPILER_RT_VISIBILITY
30 uint32_t BoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
31   void *R = *Ptr;
32   if (R == OldV) {
33     *Ptr = NewV;
34     return 1;
35   }
36   return 0;
37 }
38 #endif
39
40 /* This method is only used in value profiler mock testing.  */
41 COMPILER_RT_VISIBILITY void
42 __llvm_profile_set_num_value_sites(__llvm_profile_data *Data,
43                                    uint32_t ValueKind, uint16_t NumValueSites) {
44   *((uint16_t *)&Data->NumValueSites[ValueKind]) = NumValueSites;
45 }
46
47 /* This method is only used in value profiler mock testing.  */
48 COMPILER_RT_VISIBILITY const __llvm_profile_data *
49 __llvm_profile_iterate_data(const __llvm_profile_data *Data) {
50   return Data + 1;
51 }
52
53 /* This method is only used in value profiler mock testing.  */
54 COMPILER_RT_VISIBILITY void *
55 __llvm_get_function_addr(const __llvm_profile_data *Data) {
56   return Data->FunctionPointer;
57 }
58
59 /* Allocate an array that holds the pointers to the linked lists of
60  * value profile counter nodes. The number of element of the array
61  * is the total number of value profile sites instrumented. Returns
62  * 0 if allocation fails.
63  */
64
65 static int allocateValueProfileCounters(__llvm_profile_data *Data) {
66   uint64_t NumVSites = 0;
67   uint32_t VKI;
68   for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI)
69     NumVSites += Data->NumValueSites[VKI];
70
71   ValueProfNode **Mem =
72       (ValueProfNode **)calloc(NumVSites, sizeof(ValueProfNode *));
73   if (!Mem)
74     return 0;
75   if (!COMPILER_RT_BOOL_CMPXCHG(&Data->Values, 0, Mem)) {
76     free(Mem);
77     return 0;
78   }
79   return 1;
80 }
81
82 COMPILER_RT_VISIBILITY void
83 __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
84                                  uint32_t CounterIndex) {
85
86   __llvm_profile_data *PData = (__llvm_profile_data *)Data;
87   if (!PData)
88     return;
89
90   if (!PData->Values) {
91     if (!allocateValueProfileCounters(PData))
92       return;
93   }
94
95   ValueProfNode **ValueCounters = (ValueProfNode **)PData->Values;
96   ValueProfNode *PrevVNode = NULL;
97   ValueProfNode *CurrentVNode = ValueCounters[CounterIndex];
98
99   uint8_t VDataCount = 0;
100   while (CurrentVNode) {
101     if (TargetValue == CurrentVNode->VData.Value) {
102       CurrentVNode->VData.Count++;
103       return;
104     }
105     PrevVNode = CurrentVNode;
106     CurrentVNode = CurrentVNode->Next;
107     ++VDataCount;
108   }
109
110   if (VDataCount >= INSTR_PROF_MAX_NUM_VAL_PER_SITE)
111     return;
112
113   CurrentVNode = (ValueProfNode *)calloc(1, sizeof(ValueProfNode));
114   if (!CurrentVNode)
115     return;
116
117   CurrentVNode->VData.Value = TargetValue;
118   CurrentVNode->VData.Count++;
119
120   uint32_t Success = 0;
121   if (!ValueCounters[CounterIndex])
122     Success =
123         COMPILER_RT_BOOL_CMPXCHG(&ValueCounters[CounterIndex], 0, CurrentVNode);
124   else if (PrevVNode && !PrevVNode->Next)
125     Success = COMPILER_RT_BOOL_CMPXCHG(&(PrevVNode->Next), 0, CurrentVNode);
126
127   if (!Success) {
128     free(CurrentVNode);
129     return;
130   }
131 }
132
133 COMPILER_RT_VISIBILITY ValueProfData **
134 __llvm_profile_gather_value_data(uint64_t *ValueDataSize) {
135   size_t S = 0;
136   __llvm_profile_data *I;
137   ValueProfData **ValueDataArray;
138
139   const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
140   const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
141
142   if (!ValueDataSize)
143     return NULL;
144
145   ValueDataArray =
146       (ValueProfData **)calloc(DataEnd - DataBegin, sizeof(void *));
147   if (!ValueDataArray)
148     PROF_OOM_RETURN("Failed to write value profile data ");
149
150   /*
151    * Compute the total Size of the buffer to hold ValueProfData
152    * structures for functions with value profile data.
153    */
154   for (I = (__llvm_profile_data *)DataBegin; I != DataEnd; ++I) {
155     ValueProfRuntimeRecord R;
156     if (initializeValueProfRuntimeRecord(&R, I->NumValueSites, I->Values))
157       PROF_OOM_RETURN("Failed to write value profile data ");
158
159     /* Compute the size of ValueProfData from this runtime record.  */
160     if (getNumValueKindsRT(&R) != 0) {
161       ValueProfData *VD = NULL;
162       uint32_t VS = getValueProfDataSizeRT(&R);
163       VD = (ValueProfData *)calloc(VS, sizeof(uint8_t));
164       if (!VD)
165         PROF_OOM_RETURN("Failed to write value profile data ");
166       serializeValueProfDataFromRT(&R, VD);
167       ValueDataArray[I - DataBegin] = VD;
168       S += VS;
169     }
170     finalizeValueProfRuntimeRecord(&R);
171   }
172
173   if (!S) {
174     free(ValueDataArray);
175     ValueDataArray = NULL;
176   }
177
178   *ValueDataSize = S;
179   return ValueDataArray;
180 }