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