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