1 //=-- InstrProf.cpp - Instrumented profiling format support -----------------=// 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 // This file contains support for clang's instrumentation based PGO and 11 // coverage. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/Constants.h" 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/IR/GlobalVariable.h" 19 #include "llvm/ProfileData/InstrProf.h" 20 #include "llvm/Support/ErrorHandling.h" 21 #include "llvm/Support/ManagedStatic.h" 22 23 using namespace llvm; 24 25 namespace { 26 class InstrProfErrorCategoryType : public std::error_category { 27 const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; } 28 std::string message(int IE) const override { 29 instrprof_error E = static_cast<instrprof_error>(IE); 30 switch (E) { 31 case instrprof_error::success: 32 return "Success"; 33 case instrprof_error::eof: 34 return "End of File"; 35 case instrprof_error::unrecognized_format: 36 return "Unrecognized instrumentation profile encoding format"; 37 case instrprof_error::bad_magic: 38 return "Invalid instrumentation profile data (bad magic)"; 39 case instrprof_error::bad_header: 40 return "Invalid instrumentation profile data (file header is corrupt)"; 41 case instrprof_error::unsupported_version: 42 return "Unsupported instrumentation profile format version"; 43 case instrprof_error::unsupported_hash_type: 44 return "Unsupported instrumentation profile hash type"; 45 case instrprof_error::too_large: 46 return "Too much profile data"; 47 case instrprof_error::truncated: 48 return "Truncated profile data"; 49 case instrprof_error::malformed: 50 return "Malformed instrumentation profile data"; 51 case instrprof_error::unknown_function: 52 return "No profile data available for function"; 53 case instrprof_error::hash_mismatch: 54 return "Function control flow change detected (hash mismatch)"; 55 case instrprof_error::count_mismatch: 56 return "Function basic block count change detected (counter mismatch)"; 57 case instrprof_error::counter_overflow: 58 return "Counter overflow"; 59 case instrprof_error::value_site_count_mismatch: 60 return "Function value site count change detected (counter mismatch)"; 61 } 62 llvm_unreachable("A value of instrprof_error has no message."); 63 } 64 }; 65 } 66 67 static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory; 68 69 const std::error_category &llvm::instrprof_category() { 70 return *ErrorCategory; 71 } 72 73 namespace llvm { 74 75 std::string getPGOFuncName(StringRef RawFuncName, 76 GlobalValue::LinkageTypes Linkage, 77 StringRef FileName) { 78 79 // Function names may be prefixed with a binary '1' to indicate 80 // that the backend should not modify the symbols due to any platform 81 // naming convention. Do not include that '1' in the PGO profile name. 82 if (RawFuncName[0] == '\1') 83 RawFuncName = RawFuncName.substr(1); 84 85 std::string FuncName = RawFuncName; 86 if (llvm::GlobalValue::isLocalLinkage(Linkage)) { 87 // For local symbols, prepend the main file name to distinguish them. 88 // Do not include the full path in the file name since there's no guarantee 89 // that it will stay the same, e.g., if the files are checked out from 90 // version control in different locations. 91 if (FileName.empty()) 92 FuncName = FuncName.insert(0, "<unknown>:"); 93 else 94 FuncName = FuncName.insert(0, FileName.str() + ":"); 95 } 96 return FuncName; 97 } 98 99 std::string getPGOFuncName(const Function &F) { 100 return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName()); 101 } 102 103 GlobalVariable *createPGOFuncNameVar(Module &M, 104 GlobalValue::LinkageTypes Linkage, 105 StringRef FuncName) { 106 107 // We generally want to match the function's linkage, but available_externally 108 // and extern_weak both have the wrong semantics, and anything that doesn't 109 // need to link across compilation units doesn't need to be visible at all. 110 if (Linkage == GlobalValue::ExternalWeakLinkage) 111 Linkage = GlobalValue::LinkOnceAnyLinkage; 112 else if (Linkage == GlobalValue::AvailableExternallyLinkage) 113 Linkage = GlobalValue::LinkOnceODRLinkage; 114 else if (Linkage == GlobalValue::InternalLinkage || 115 Linkage == GlobalValue::ExternalLinkage) 116 Linkage = GlobalValue::PrivateLinkage; 117 118 auto *Value = ConstantDataArray::getString(M.getContext(), FuncName, false); 119 auto FuncNameVar = 120 new GlobalVariable(M, Value->getType(), true, Linkage, Value, 121 Twine(getInstrProfNameVarPrefix()) + FuncName); 122 123 // Hide the symbol so that we correctly get a copy for each executable. 124 if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage())) 125 FuncNameVar->setVisibility(GlobalValue::HiddenVisibility); 126 127 return FuncNameVar; 128 } 129 130 GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName) { 131 return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName); 132 } 133 134 #define INSTR_PROF_COMMON_API_IMPL 135 #include "llvm/ProfileData/InstrProfData.inc" 136 137 138 /*! 139 * \brief ValueProfRecordClosure Interface implementation for InstrProfRecord 140 * class. These C wrappers are used as adaptors so that C++ code can be 141 * invoked as callbacks. 142 */ 143 uint32_t getNumValueKindsInstrProf(const void *Record) { 144 return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds(); 145 } 146 147 uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) { 148 return reinterpret_cast<const InstrProfRecord *>(Record) 149 ->getNumValueSites(VKind); 150 } 151 152 uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) { 153 return reinterpret_cast<const InstrProfRecord *>(Record) 154 ->getNumValueData(VKind); 155 } 156 157 uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK, 158 uint32_t S) { 159 return reinterpret_cast<const InstrProfRecord *>(R) 160 ->getNumValueDataForSite(VK, S); 161 } 162 163 void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst, 164 uint32_t K, uint32_t S, 165 uint64_t (*Mapper)(uint32_t, uint64_t)) { 166 return reinterpret_cast<const InstrProfRecord *>(R) 167 ->getValueForSite(Dst, K, S, Mapper); 168 } 169 170 uint64_t stringToHash(uint32_t ValueKind, uint64_t Value) { 171 switch (ValueKind) { 172 case IPVK_IndirectCallTarget: 173 return IndexedInstrProf::ComputeHash(IndexedInstrProf::HashType, 174 (const char *)Value); 175 break; 176 default: 177 llvm_unreachable("value kind not handled !"); 178 } 179 return Value; 180 } 181 182 ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) { 183 return (ValueProfData *)(new (::operator new(TotalSizeInBytes)) 184 ValueProfData()); 185 } 186 187 static ValueProfRecordClosure InstrProfRecordClosure = { 188 0, 189 getNumValueKindsInstrProf, 190 getNumValueSitesInstrProf, 191 getNumValueDataInstrProf, 192 getNumValueDataForSiteInstrProf, 193 stringToHash, 194 getValueForSiteInstrProf, 195 allocValueProfDataInstrProf 196 }; 197 198 // Wrapper implementation using the closure mechanism. 199 uint32_t ValueProfData::getSize(const InstrProfRecord &Record) { 200 InstrProfRecordClosure.Record = &Record; 201 return getValueProfDataSize(&InstrProfRecordClosure); 202 } 203 204 // Wrapper implementation using the closure mechanism. 205 std::unique_ptr<ValueProfData> 206 ValueProfData::serializeFrom(const InstrProfRecord &Record) { 207 InstrProfRecordClosure.Record = &Record; 208 209 std::unique_ptr<ValueProfData> VPD( 210 serializeValueProfDataFrom(&InstrProfRecordClosure, nullptr)); 211 return VPD; 212 } 213 214 void ValueProfRecord::deserializeTo(InstrProfRecord &Record, 215 InstrProfRecord::ValueMapType *VMap) { 216 Record.reserveSites(Kind, NumValueSites); 217 218 InstrProfValueData *ValueData = getValueProfRecordValueData(this); 219 for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) { 220 uint8_t ValueDataCount = this->SiteCountArray[VSite]; 221 Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap); 222 ValueData += ValueDataCount; 223 } 224 } 225 226 // For writing/serializing, Old is the host endianness, and New is 227 // byte order intended on disk. For Reading/deserialization, Old 228 // is the on-disk source endianness, and New is the host endianness. 229 void ValueProfRecord::swapBytes(support::endianness Old, 230 support::endianness New) { 231 using namespace support; 232 if (Old == New) 233 return; 234 235 if (getHostEndianness() != Old) { 236 sys::swapByteOrder<uint32_t>(NumValueSites); 237 sys::swapByteOrder<uint32_t>(Kind); 238 } 239 uint32_t ND = getValueProfRecordNumValueData(this); 240 InstrProfValueData *VD = getValueProfRecordValueData(this); 241 242 // No need to swap byte array: SiteCountArrray. 243 for (uint32_t I = 0; I < ND; I++) { 244 sys::swapByteOrder<uint64_t>(VD[I].Value); 245 sys::swapByteOrder<uint64_t>(VD[I].Count); 246 } 247 if (getHostEndianness() == Old) { 248 sys::swapByteOrder<uint32_t>(NumValueSites); 249 sys::swapByteOrder<uint32_t>(Kind); 250 } 251 } 252 253 void ValueProfData::deserializeTo(InstrProfRecord &Record, 254 InstrProfRecord::ValueMapType *VMap) { 255 if (NumValueKinds == 0) 256 return; 257 258 ValueProfRecord *VR = getFirstValueProfRecord(this); 259 for (uint32_t K = 0; K < NumValueKinds; K++) { 260 VR->deserializeTo(Record, VMap); 261 VR = getValueProfRecordNext(VR); 262 } 263 } 264 265 template <class T> 266 static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) { 267 using namespace support; 268 if (Orig == little) 269 return endian::readNext<T, little, unaligned>(D); 270 else 271 return endian::readNext<T, big, unaligned>(D); 272 } 273 274 static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) { 275 return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize)) 276 ValueProfData()); 277 } 278 279 instrprof_error ValueProfData::checkIntegrity() { 280 if (NumValueKinds > IPVK_Last + 1) 281 return instrprof_error::malformed; 282 // Total size needs to be mulltiple of quadword size. 283 if (TotalSize % sizeof(uint64_t)) 284 return instrprof_error::malformed; 285 286 ValueProfRecord *VR = getFirstValueProfRecord(this); 287 for (uint32_t K = 0; K < this->NumValueKinds; K++) { 288 if (VR->Kind > IPVK_Last) 289 return instrprof_error::malformed; 290 VR = getValueProfRecordNext(VR); 291 if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize) 292 return instrprof_error::malformed; 293 } 294 return instrprof_error::success; 295 } 296 297 ErrorOr<std::unique_ptr<ValueProfData>> 298 ValueProfData::getValueProfData(const unsigned char *D, 299 const unsigned char *const BufferEnd, 300 support::endianness Endianness) { 301 using namespace support; 302 if (D + sizeof(ValueProfData) > BufferEnd) 303 return instrprof_error::truncated; 304 305 const unsigned char *Header = D; 306 uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness); 307 if (D + TotalSize > BufferEnd) 308 return instrprof_error::too_large; 309 310 std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize); 311 memcpy(VPD.get(), D, TotalSize); 312 // Byte swap. 313 VPD->swapBytesToHost(Endianness); 314 315 instrprof_error EC = VPD->checkIntegrity(); 316 if (EC != instrprof_error::success) 317 return EC; 318 319 return std::move(VPD); 320 } 321 322 void ValueProfData::swapBytesToHost(support::endianness Endianness) { 323 using namespace support; 324 if (Endianness == getHostEndianness()) 325 return; 326 327 sys::swapByteOrder<uint32_t>(TotalSize); 328 sys::swapByteOrder<uint32_t>(NumValueKinds); 329 330 ValueProfRecord *VR = getFirstValueProfRecord(this); 331 for (uint32_t K = 0; K < NumValueKinds; K++) { 332 VR->swapBytes(Endianness, getHostEndianness()); 333 VR = getValueProfRecordNext(VR); 334 } 335 } 336 337 void ValueProfData::swapBytesFromHost(support::endianness Endianness) { 338 using namespace support; 339 if (Endianness == getHostEndianness()) 340 return; 341 342 ValueProfRecord *VR = getFirstValueProfRecord(this); 343 for (uint32_t K = 0; K < NumValueKinds; K++) { 344 ValueProfRecord *NVR = getValueProfRecordNext(VR); 345 VR->swapBytes(getHostEndianness(), Endianness); 346 VR = NVR; 347 } 348 sys::swapByteOrder<uint32_t>(TotalSize); 349 sys::swapByteOrder<uint32_t>(NumValueKinds); 350 } 351 352 } 353