1480093f4SDimitry Andric/*===-- InstrProfData.inc - instr profiling runtime structures -*- C++ -*-=== *\ 2480093f4SDimitry Andric|* 3480093f4SDimitry Andric|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric|* See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric|* 7480093f4SDimitry Andric\*===----------------------------------------------------------------------===*/ 8480093f4SDimitry Andric/* 9fe6060f1SDimitry Andric * This is the main file that defines all the data structure, signature, 10480093f4SDimitry Andric * constant literals that are shared across profiling runtime library, 11480093f4SDimitry Andric * compiler (instrumentation), and host tools (reader/writer). The entities 12480093f4SDimitry Andric * defined in this file affect the profile runtime ABI, the raw profile format, 13480093f4SDimitry Andric * or both. 14480093f4SDimitry Andric * 15fe6060f1SDimitry Andric * The file has two identical copies. The primary copy lives in LLVM and 16480093f4SDimitry Andric * the other one sits in compiler-rt/lib/profile directory. To make changes 17fe6060f1SDimitry Andric * in this file, first modify the primary copy and copy it over to compiler-rt. 18480093f4SDimitry Andric * Testing of any change in this file can start only after the two copies are 19480093f4SDimitry Andric * synced up. 20480093f4SDimitry Andric * 21480093f4SDimitry Andric * The first part of the file includes macros that defines types, names, and 22480093f4SDimitry Andric * initializers for the member fields of the core data structures. The field 23480093f4SDimitry Andric * declarations for one structure is enabled by defining the field activation 24480093f4SDimitry Andric * macro associated with that structure. Only one field activation record 25480093f4SDimitry Andric * can be defined at one time and the rest definitions will be filtered out by 26480093f4SDimitry Andric * the preprocessor. 27480093f4SDimitry Andric * 28480093f4SDimitry Andric * Examples of how the template is used to instantiate structure definition: 29480093f4SDimitry Andric * 1. To declare a structure: 30480093f4SDimitry Andric * 31480093f4SDimitry Andric * struct ProfData { 32480093f4SDimitry Andric * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ 33480093f4SDimitry Andric * Type Name; 34480093f4SDimitry Andric * #include "llvm/ProfileData/InstrProfData.inc" 35480093f4SDimitry Andric * }; 36480093f4SDimitry Andric * 37480093f4SDimitry Andric * 2. To construct LLVM type arrays for the struct type: 38480093f4SDimitry Andric * 39480093f4SDimitry Andric * Type *DataTypes[] = { 40480093f4SDimitry Andric * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ 41480093f4SDimitry Andric * LLVMType, 42480093f4SDimitry Andric * #include "llvm/ProfileData/InstrProfData.inc" 43480093f4SDimitry Andric * }; 44480093f4SDimitry Andric * 45480093f4SDimitry Andric * 4. To construct constant array for the initializers: 46480093f4SDimitry Andric * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ 47480093f4SDimitry Andric * Initializer, 48480093f4SDimitry Andric * Constant *ConstantVals[] = { 49480093f4SDimitry Andric * #include "llvm/ProfileData/InstrProfData.inc" 50480093f4SDimitry Andric * }; 51480093f4SDimitry Andric * 52480093f4SDimitry Andric * 53480093f4SDimitry Andric * The second part of the file includes definitions all other entities that 54480093f4SDimitry Andric * are related to runtime ABI and format. When no field activation macro is 55480093f4SDimitry Andric * defined, this file can be included to introduce the definitions. 56480093f4SDimitry Andric * 57480093f4SDimitry Andric\*===----------------------------------------------------------------------===*/ 58480093f4SDimitry Andric 59480093f4SDimitry Andric/* Functions marked with INSTR_PROF_VISIBILITY must have hidden visibility in 60480093f4SDimitry Andric * the compiler runtime. */ 61480093f4SDimitry Andric#ifndef INSTR_PROF_VISIBILITY 62480093f4SDimitry Andric#define INSTR_PROF_VISIBILITY 63480093f4SDimitry Andric#endif 64480093f4SDimitry Andric 65480093f4SDimitry Andric/* INSTR_PROF_DATA start. */ 66480093f4SDimitry Andric/* Definition of member fields of the per-function control structure. */ 67480093f4SDimitry Andric#ifndef INSTR_PROF_DATA 68480093f4SDimitry Andric#define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) 69480093f4SDimitry Andric#else 70480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 71480093f4SDimitry Andric#endif 72480093f4SDimitry AndricINSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ 73480093f4SDimitry Andric ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ 74480093f4SDimitry Andric IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName())))) 75480093f4SDimitry AndricINSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ 76480093f4SDimitry Andric ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ 77480093f4SDimitry Andric Inc->getHash()->getZExtValue())) 78349cc55cSDimitry AndricINSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr) 79480093f4SDimitry Andric/* This is used to map function pointers for the indirect call targets to 80480093f4SDimitry Andric * function name hashes during the conversion from raw to merged profile 81480093f4SDimitry Andric * data. 82480093f4SDimitry Andric */ 83480093f4SDimitry AndricINSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \ 84480093f4SDimitry Andric FunctionAddr) 85480093f4SDimitry AndricINSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \ 86480093f4SDimitry Andric ValuesPtrExpr) 87480093f4SDimitry AndricINSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \ 88480093f4SDimitry Andric ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters)) 89480093f4SDimitry AndricINSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \ 90480093f4SDimitry Andric ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) 91480093f4SDimitry Andric#undef INSTR_PROF_DATA 92480093f4SDimitry Andric/* INSTR_PROF_DATA end. */ 93480093f4SDimitry Andric 94480093f4SDimitry Andric 95480093f4SDimitry Andric/* This is an internal data structure used by value profiler. It 96480093f4SDimitry Andric * is defined here to allow serialization code sharing by LLVM 97480093f4SDimitry Andric * to be used in unit test. 98480093f4SDimitry Andric * 99480093f4SDimitry Andric * typedef struct ValueProfNode { 100480093f4SDimitry Andric * // InstrProfValueData VData; 101480093f4SDimitry Andric * uint64_t Value; 102480093f4SDimitry Andric * uint64_t Count; 103480093f4SDimitry Andric * struct ValueProfNode *Next; 104480093f4SDimitry Andric * } ValueProfNode; 105480093f4SDimitry Andric */ 106480093f4SDimitry Andric/* INSTR_PROF_VALUE_NODE start. */ 107480093f4SDimitry Andric#ifndef INSTR_PROF_VALUE_NODE 108480093f4SDimitry Andric#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer) 109480093f4SDimitry Andric#else 110480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 111480093f4SDimitry Andric#endif 112480093f4SDimitry AndricINSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \ 113480093f4SDimitry Andric ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0)) 114480093f4SDimitry AndricINSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \ 115480093f4SDimitry Andric ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0)) 116480093f4SDimitry AndricINSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \ 117480093f4SDimitry Andric ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0)) 118480093f4SDimitry Andric#undef INSTR_PROF_VALUE_NODE 119480093f4SDimitry Andric/* INSTR_PROF_VALUE_NODE end. */ 120480093f4SDimitry Andric 121480093f4SDimitry Andric/* INSTR_PROF_RAW_HEADER start */ 122480093f4SDimitry Andric/* Definition of member fields of the raw profile header data structure. */ 123480093f4SDimitry Andric#ifndef INSTR_PROF_RAW_HEADER 124480093f4SDimitry Andric#define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) 125480093f4SDimitry Andric#else 126480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 127480093f4SDimitry Andric#endif 128480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic()) 129480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version()) 1306e75b2fbSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL)) 13104eeddc0SDimitry Andric/* FIXME: A more accurate name is NumData */ 132480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize) 133480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters) 13404eeddc0SDimitry Andric/* FIXME: A more accurate name is NumCounters */ 135480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize) 136480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters) 137480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize) 138349cc55cSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, 139349cc55cSDimitry Andric (uintptr_t)CountersBegin - (uintptr_t)DataBegin) 140480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) 141480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) 142480093f4SDimitry Andric#undef INSTR_PROF_RAW_HEADER 143480093f4SDimitry Andric/* INSTR_PROF_RAW_HEADER end */ 144480093f4SDimitry Andric 145480093f4SDimitry Andric/* VALUE_PROF_FUNC_PARAM start */ 146480093f4SDimitry Andric/* Definition of parameter types of the runtime API used to do value profiling 147480093f4SDimitry Andric * for a given value site. 148480093f4SDimitry Andric */ 149480093f4SDimitry Andric#ifndef VALUE_PROF_FUNC_PARAM 150480093f4SDimitry Andric#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) 151480093f4SDimitry Andric#define INSTR_PROF_COMMA 152480093f4SDimitry Andric#else 153480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 154480093f4SDimitry Andric#define INSTR_PROF_COMMA , 155480093f4SDimitry Andric#endif 156480093f4SDimitry AndricVALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \ 157480093f4SDimitry Andric INSTR_PROF_COMMA 158480093f4SDimitry AndricVALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA 159480093f4SDimitry AndricVALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) 160480093f4SDimitry Andric#undef VALUE_PROF_FUNC_PARAM 161480093f4SDimitry Andric#undef INSTR_PROF_COMMA 162480093f4SDimitry Andric/* VALUE_PROF_FUNC_PARAM end */ 163480093f4SDimitry Andric 164480093f4SDimitry Andric/* VALUE_PROF_KIND start */ 165480093f4SDimitry Andric#ifndef VALUE_PROF_KIND 166480093f4SDimitry Andric#define VALUE_PROF_KIND(Enumerator, Value, Descr) 167480093f4SDimitry Andric#else 168480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 169480093f4SDimitry Andric#endif 170480093f4SDimitry Andric/* For indirect function call value profiling, the addresses of the target 171480093f4SDimitry Andric * functions are profiled by the instrumented code. The target addresses are 172480093f4SDimitry Andric * written in the raw profile data and converted to target function name's MD5 173480093f4SDimitry Andric * hash by the profile reader during deserialization. Typically, this happens 174480093f4SDimitry Andric * when the raw profile data is read during profile merging. 175480093f4SDimitry Andric * 176480093f4SDimitry Andric * For this remapping the ProfData is used. ProfData contains both the function 177480093f4SDimitry Andric * name hash and the function address. 178480093f4SDimitry Andric */ 179480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_IndirectCallTarget, 0, "indirect call target") 180480093f4SDimitry Andric/* For memory intrinsic functions size profiling. */ 181480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_MemOPSize, 1, "memory intrinsic functions size") 182480093f4SDimitry Andric/* These two kinds must be the last to be 183480093f4SDimitry Andric * declared. This is to make sure the string 184480093f4SDimitry Andric * array created with the template can be 185480093f4SDimitry Andric * indexed with the kind value. 186480093f4SDimitry Andric */ 187480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget, "first") 188480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize, "last") 189480093f4SDimitry Andric 190480093f4SDimitry Andric#undef VALUE_PROF_KIND 191480093f4SDimitry Andric/* VALUE_PROF_KIND end */ 192480093f4SDimitry Andric 1935ffd83dbSDimitry Andric#undef COVMAP_V2_OR_V3 1945ffd83dbSDimitry Andric#ifdef COVMAP_V2 1955ffd83dbSDimitry Andric#define COVMAP_V2_OR_V3 1965ffd83dbSDimitry Andric#endif 1975ffd83dbSDimitry Andric#ifdef COVMAP_V3 1985ffd83dbSDimitry Andric#define COVMAP_V2_OR_V3 1995ffd83dbSDimitry Andric#endif 2005ffd83dbSDimitry Andric 201480093f4SDimitry Andric/* COVMAP_FUNC_RECORD start */ 202480093f4SDimitry Andric/* Definition of member fields of the function record structure in coverage 203480093f4SDimitry Andric * map. 204480093f4SDimitry Andric */ 205480093f4SDimitry Andric#ifndef COVMAP_FUNC_RECORD 206480093f4SDimitry Andric#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Initializer) 207480093f4SDimitry Andric#else 208480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 209480093f4SDimitry Andric#endif 210480093f4SDimitry Andric#ifdef COVMAP_V1 211480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), \ 212480093f4SDimitry Andric NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \ 213480093f4SDimitry Andric llvm::Type::getInt8PtrTy(Ctx))) 214480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ 215480093f4SDimitry Andric llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \ 216480093f4SDimitry Andric NameValue.size())) 2175ffd83dbSDimitry Andric#endif 2185ffd83dbSDimitry Andric#ifdef COVMAP_V2_OR_V3 219480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const int64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ 2205ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2215ffd83dbSDimitry Andric llvm::Type::getInt64Ty(Ctx), NameHash)) 222480093f4SDimitry Andric#endif 223480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \ 2245ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2255ffd83dbSDimitry Andric llvm::Type::getInt32Ty(Ctx), CoverageMapping.size())) 226480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ 2275ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2285ffd83dbSDimitry Andric llvm::Type::getInt64Ty(Ctx), FuncHash)) 2295ffd83dbSDimitry Andric#ifdef COVMAP_V3 2305ffd83dbSDimitry AndricCOVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FilenamesRef, \ 2315ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2325ffd83dbSDimitry Andric llvm::Type::getInt64Ty(Ctx), FilenamesRef)) 2335ffd83dbSDimitry AndricCOVMAP_FUNC_RECORD(const char, \ 2345ffd83dbSDimitry Andric llvm::ArrayType::get(llvm::Type::getInt8Ty(Ctx), \ 2355ffd83dbSDimitry Andric CoverageMapping.size()), \ 2365ffd83dbSDimitry Andric CoverageMapping, 2375ffd83dbSDimitry Andric llvm::ConstantDataArray::getRaw( \ 2385ffd83dbSDimitry Andric CoverageMapping, CoverageMapping.size(), \ 2395ffd83dbSDimitry Andric llvm::Type::getInt8Ty(Ctx))) 2405ffd83dbSDimitry Andric#endif 241480093f4SDimitry Andric#undef COVMAP_FUNC_RECORD 242480093f4SDimitry Andric/* COVMAP_FUNC_RECORD end. */ 243480093f4SDimitry Andric 244480093f4SDimitry Andric/* COVMAP_HEADER start */ 245480093f4SDimitry Andric/* Definition of member fields of coverage map header. 246480093f4SDimitry Andric */ 247480093f4SDimitry Andric#ifndef COVMAP_HEADER 248480093f4SDimitry Andric#define COVMAP_HEADER(Type, LLVMType, Name, Initializer) 249480093f4SDimitry Andric#else 250480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 251480093f4SDimitry Andric#endif 252480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, NRecords, \ 2535ffd83dbSDimitry Andric llvm::ConstantInt::get(Int32Ty, NRecords)) 254480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, FilenamesSize, \ 255480093f4SDimitry Andric llvm::ConstantInt::get(Int32Ty, FilenamesSize)) 256480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \ 257480093f4SDimitry Andric llvm::ConstantInt::get(Int32Ty, CoverageMappingSize)) 258480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, Version, \ 259480093f4SDimitry Andric llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion)) 260480093f4SDimitry Andric#undef COVMAP_HEADER 261480093f4SDimitry Andric/* COVMAP_HEADER end. */ 262480093f4SDimitry Andric 263480093f4SDimitry Andric 264480093f4SDimitry Andric#ifdef INSTR_PROF_SECT_ENTRY 265480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 266480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_data, \ 267480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \ 268480093f4SDimitry Andric INSTR_PROF_DATA_COFF, "__DATA,") 269480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_cnts, \ 270480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \ 271480093f4SDimitry Andric INSTR_PROF_CNTS_COFF, "__DATA,") 272480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_name, \ 273480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \ 274480093f4SDimitry Andric INSTR_PROF_NAME_COFF, "__DATA,") 275480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_vals, \ 276480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \ 277480093f4SDimitry Andric INSTR_PROF_VALS_COFF, "__DATA,") 278480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_vnodes, \ 279480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \ 280480093f4SDimitry Andric INSTR_PROF_VNODES_COFF, "__DATA,") 281480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_covmap, \ 282480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \ 283480093f4SDimitry Andric INSTR_PROF_COVMAP_COFF, "__LLVM_COV,") 2845ffd83dbSDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_covfun, \ 2855ffd83dbSDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_COVFUN_COMMON), \ 2865ffd83dbSDimitry Andric INSTR_PROF_COVFUN_COFF, "__LLVM_COV,") 287480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_orderfile, \ 288480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON), \ 289480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COFF), "__DATA,") 290480093f4SDimitry Andric 291480093f4SDimitry Andric#undef INSTR_PROF_SECT_ENTRY 292480093f4SDimitry Andric#endif 293480093f4SDimitry Andric 294480093f4SDimitry Andric 295480093f4SDimitry Andric#ifdef INSTR_PROF_VALUE_PROF_DATA 296480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 297480093f4SDimitry Andric 298480093f4SDimitry Andric#define INSTR_PROF_MAX_NUM_VAL_PER_SITE 255 299480093f4SDimitry Andric/*! 300480093f4SDimitry Andric * This is the header of the data structure that defines the on-disk 301480093f4SDimitry Andric * layout of the value profile data of a particular kind for one function. 302480093f4SDimitry Andric */ 303480093f4SDimitry Andrictypedef struct ValueProfRecord { 304480093f4SDimitry Andric /* The kind of the value profile record. */ 305480093f4SDimitry Andric uint32_t Kind; 306480093f4SDimitry Andric /* 307480093f4SDimitry Andric * The number of value profile sites. It is guaranteed to be non-zero; 308480093f4SDimitry Andric * otherwise the record for this kind won't be emitted. 309480093f4SDimitry Andric */ 310480093f4SDimitry Andric uint32_t NumValueSites; 311480093f4SDimitry Andric /* 312480093f4SDimitry Andric * The first element of the array that stores the number of profiled 313480093f4SDimitry Andric * values for each value site. The size of the array is NumValueSites. 314480093f4SDimitry Andric * Since NumValueSites is greater than zero, there is at least one 315480093f4SDimitry Andric * element in the array. 316480093f4SDimitry Andric */ 317480093f4SDimitry Andric uint8_t SiteCountArray[1]; 318480093f4SDimitry Andric 319480093f4SDimitry Andric /* 320480093f4SDimitry Andric * The fake declaration is for documentation purpose only. 321480093f4SDimitry Andric * Align the start of next field to be on 8 byte boundaries. 322480093f4SDimitry Andric uint8_t Padding[X]; 323480093f4SDimitry Andric */ 324480093f4SDimitry Andric 325480093f4SDimitry Andric /* The array of value profile data. The size of the array is the sum 326480093f4SDimitry Andric * of all elements in SiteCountArray[]. 327480093f4SDimitry Andric InstrProfValueData ValueData[]; 328480093f4SDimitry Andric */ 329480093f4SDimitry Andric 330480093f4SDimitry Andric#ifdef __cplusplus 331480093f4SDimitry Andric /*! 332480093f4SDimitry Andric * Return the number of value sites. 333480093f4SDimitry Andric */ 334480093f4SDimitry Andric uint32_t getNumValueSites() const { return NumValueSites; } 335480093f4SDimitry Andric /*! 336480093f4SDimitry Andric * Read data from this record and save it to Record. 337480093f4SDimitry Andric */ 338480093f4SDimitry Andric void deserializeTo(InstrProfRecord &Record, 339480093f4SDimitry Andric InstrProfSymtab *SymTab); 340480093f4SDimitry Andric /* 341480093f4SDimitry Andric * In-place byte swap: 342480093f4SDimitry Andric * Do byte swap for this instance. \c Old is the original order before 343480093f4SDimitry Andric * the swap, and \c New is the New byte order. 344480093f4SDimitry Andric */ 345480093f4SDimitry Andric void swapBytes(support::endianness Old, support::endianness New); 346480093f4SDimitry Andric#endif 347480093f4SDimitry Andric} ValueProfRecord; 348480093f4SDimitry Andric 349480093f4SDimitry Andric/*! 350480093f4SDimitry Andric * Per-function header/control data structure for value profiling 351480093f4SDimitry Andric * data in indexed format. 352480093f4SDimitry Andric */ 353480093f4SDimitry Andrictypedef struct ValueProfData { 354480093f4SDimitry Andric /* 355480093f4SDimitry Andric * Total size in bytes including this field. It must be a multiple 356480093f4SDimitry Andric * of sizeof(uint64_t). 357480093f4SDimitry Andric */ 358480093f4SDimitry Andric uint32_t TotalSize; 359480093f4SDimitry Andric /* 360480093f4SDimitry Andric *The number of value profile kinds that has value profile data. 361480093f4SDimitry Andric * In this implementation, a value profile kind is considered to 362480093f4SDimitry Andric * have profile data if the number of value profile sites for the 363480093f4SDimitry Andric * kind is not zero. More aggressively, the implementation can 364480093f4SDimitry Andric * choose to check the actual data value: if none of the value sites 365480093f4SDimitry Andric * has any profiled values, the kind can be skipped. 366480093f4SDimitry Andric */ 367480093f4SDimitry Andric uint32_t NumValueKinds; 368480093f4SDimitry Andric 369480093f4SDimitry Andric /* 370480093f4SDimitry Andric * Following are a sequence of variable length records. The prefix/header 371480093f4SDimitry Andric * of each record is defined by ValueProfRecord type. The number of 372480093f4SDimitry Andric * records is NumValueKinds. 373480093f4SDimitry Andric * ValueProfRecord Record_1; 374480093f4SDimitry Andric * ValueProfRecord Record_N; 375480093f4SDimitry Andric */ 376480093f4SDimitry Andric 377480093f4SDimitry Andric#if __cplusplus 378480093f4SDimitry Andric /*! 379480093f4SDimitry Andric * Return the total size in bytes of the on-disk value profile data 380480093f4SDimitry Andric * given the data stored in Record. 381480093f4SDimitry Andric */ 382480093f4SDimitry Andric static uint32_t getSize(const InstrProfRecord &Record); 383480093f4SDimitry Andric /*! 384480093f4SDimitry Andric * Return a pointer to \c ValueProfData instance ready to be streamed. 385480093f4SDimitry Andric */ 386480093f4SDimitry Andric static std::unique_ptr<ValueProfData> 387480093f4SDimitry Andric serializeFrom(const InstrProfRecord &Record); 388480093f4SDimitry Andric /*! 389480093f4SDimitry Andric * Check the integrity of the record. 390480093f4SDimitry Andric */ 391480093f4SDimitry Andric Error checkIntegrity(); 392480093f4SDimitry Andric /*! 393480093f4SDimitry Andric * Return a pointer to \c ValueProfileData instance ready to be read. 394480093f4SDimitry Andric * All data in the instance are properly byte swapped. The input 395480093f4SDimitry Andric * data is assumed to be in little endian order. 396480093f4SDimitry Andric */ 397480093f4SDimitry Andric static Expected<std::unique_ptr<ValueProfData>> 398480093f4SDimitry Andric getValueProfData(const unsigned char *SrcBuffer, 399480093f4SDimitry Andric const unsigned char *const SrcBufferEnd, 400480093f4SDimitry Andric support::endianness SrcDataEndianness); 401480093f4SDimitry Andric /*! 402480093f4SDimitry Andric * Swap byte order from \c Endianness order to host byte order. 403480093f4SDimitry Andric */ 404480093f4SDimitry Andric void swapBytesToHost(support::endianness Endianness); 405480093f4SDimitry Andric /*! 406480093f4SDimitry Andric * Swap byte order from host byte order to \c Endianness order. 407480093f4SDimitry Andric */ 408480093f4SDimitry Andric void swapBytesFromHost(support::endianness Endianness); 409480093f4SDimitry Andric /*! 410480093f4SDimitry Andric * Return the total size of \c ValueProfileData. 411480093f4SDimitry Andric */ 412480093f4SDimitry Andric uint32_t getSize() const { return TotalSize; } 413480093f4SDimitry Andric /*! 414480093f4SDimitry Andric * Read data from this data and save it to \c Record. 415480093f4SDimitry Andric */ 416480093f4SDimitry Andric void deserializeTo(InstrProfRecord &Record, 417480093f4SDimitry Andric InstrProfSymtab *SymTab); 418480093f4SDimitry Andric void operator delete(void *ptr) { ::operator delete(ptr); } 419480093f4SDimitry Andric#endif 420480093f4SDimitry Andric} ValueProfData; 421480093f4SDimitry Andric 422480093f4SDimitry Andric/* 423480093f4SDimitry Andric * The closure is designed to abstact away two types of value profile data: 424480093f4SDimitry Andric * - InstrProfRecord which is the primary data structure used to 425480093f4SDimitry Andric * represent profile data in host tools (reader, writer, and profile-use) 426480093f4SDimitry Andric * - value profile runtime data structure suitable to be used by C 427480093f4SDimitry Andric * runtime library. 428480093f4SDimitry Andric * 429480093f4SDimitry Andric * Both sources of data need to serialize to disk/memory-buffer in common 430480093f4SDimitry Andric * format: ValueProfData. The abstraction allows compiler-rt's raw profiler 431480093f4SDimitry Andric * writer to share the same format and code with indexed profile writer. 432480093f4SDimitry Andric * 433480093f4SDimitry Andric * For documentation of the member methods below, refer to corresponding methods 434480093f4SDimitry Andric * in class InstrProfRecord. 435480093f4SDimitry Andric */ 436480093f4SDimitry Andrictypedef struct ValueProfRecordClosure { 437480093f4SDimitry Andric const void *Record; 438480093f4SDimitry Andric uint32_t (*GetNumValueKinds)(const void *Record); 439480093f4SDimitry Andric uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind); 440480093f4SDimitry Andric uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind); 441480093f4SDimitry Andric uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S); 442480093f4SDimitry Andric 443480093f4SDimitry Andric /* 444480093f4SDimitry Andric * After extracting the value profile data from the value profile record, 445480093f4SDimitry Andric * this method is used to map the in-memory value to on-disk value. If 446480093f4SDimitry Andric * the method is null, value will be written out untranslated. 447480093f4SDimitry Andric */ 448480093f4SDimitry Andric uint64_t (*RemapValueData)(uint32_t, uint64_t Value); 449480093f4SDimitry Andric void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K, 450480093f4SDimitry Andric uint32_t S); 451480093f4SDimitry Andric ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes); 452480093f4SDimitry Andric} ValueProfRecordClosure; 453480093f4SDimitry Andric 454480093f4SDimitry AndricINSTR_PROF_VISIBILITY ValueProfRecord * 455480093f4SDimitry AndricgetFirstValueProfRecord(ValueProfData *VPD); 456480093f4SDimitry AndricINSTR_PROF_VISIBILITY ValueProfRecord * 457480093f4SDimitry AndricgetValueProfRecordNext(ValueProfRecord *VPR); 458480093f4SDimitry AndricINSTR_PROF_VISIBILITY InstrProfValueData * 459480093f4SDimitry AndricgetValueProfRecordValueData(ValueProfRecord *VPR); 460480093f4SDimitry AndricINSTR_PROF_VISIBILITY uint32_t 461480093f4SDimitry AndricgetValueProfRecordHeaderSize(uint32_t NumValueSites); 462480093f4SDimitry Andric 463480093f4SDimitry Andric#undef INSTR_PROF_VALUE_PROF_DATA 464480093f4SDimitry Andric#endif /* INSTR_PROF_VALUE_PROF_DATA */ 465480093f4SDimitry Andric 466480093f4SDimitry Andric 467480093f4SDimitry Andric#ifdef INSTR_PROF_COMMON_API_IMPL 468480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 469480093f4SDimitry Andric#ifdef __cplusplus 470480093f4SDimitry Andric#define INSTR_PROF_INLINE inline 471480093f4SDimitry Andric#define INSTR_PROF_NULLPTR nullptr 472480093f4SDimitry Andric#else 473480093f4SDimitry Andric#define INSTR_PROF_INLINE 474480093f4SDimitry Andric#define INSTR_PROF_NULLPTR NULL 475480093f4SDimitry Andric#endif 476480093f4SDimitry Andric 477480093f4SDimitry Andric#ifndef offsetof 478480093f4SDimitry Andric#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 479480093f4SDimitry Andric#endif 480480093f4SDimitry Andric 481480093f4SDimitry Andric/*! 482480093f4SDimitry Andric * Return the \c ValueProfRecord header size including the 483480093f4SDimitry Andric * padding bytes. 484480093f4SDimitry Andric */ 485480093f4SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 486480093f4SDimitry Andricuint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) { 487480093f4SDimitry Andric uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) + 488480093f4SDimitry Andric sizeof(uint8_t) * NumValueSites; 489480093f4SDimitry Andric /* Round the size to multiple of 8 bytes. */ 490480093f4SDimitry Andric Size = (Size + 7) & ~7; 491480093f4SDimitry Andric return Size; 492480093f4SDimitry Andric} 493480093f4SDimitry Andric 494480093f4SDimitry Andric/*! 495480093f4SDimitry Andric * Return the total size of the value profile record including the 496480093f4SDimitry Andric * header and the value data. 497480093f4SDimitry Andric */ 498480093f4SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 499480093f4SDimitry Andricuint32_t getValueProfRecordSize(uint32_t NumValueSites, 500480093f4SDimitry Andric uint32_t NumValueData) { 501480093f4SDimitry Andric return getValueProfRecordHeaderSize(NumValueSites) + 502480093f4SDimitry Andric sizeof(InstrProfValueData) * NumValueData; 503480093f4SDimitry Andric} 504480093f4SDimitry Andric 505480093f4SDimitry Andric/*! 506480093f4SDimitry Andric * Return the pointer to the start of value data array. 507480093f4SDimitry Andric */ 508480093f4SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 509480093f4SDimitry AndricInstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { 510480093f4SDimitry Andric return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize( 511480093f4SDimitry Andric This->NumValueSites)); 512480093f4SDimitry Andric} 513480093f4SDimitry Andric 514480093f4SDimitry Andric/*! 515480093f4SDimitry Andric * Return the total number of value data for \c This record. 516480093f4SDimitry Andric */ 517480093f4SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 518480093f4SDimitry Andricuint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { 519480093f4SDimitry Andric uint32_t NumValueData = 0; 520480093f4SDimitry Andric uint32_t I; 521480093f4SDimitry Andric for (I = 0; I < This->NumValueSites; I++) 522480093f4SDimitry Andric NumValueData += This->SiteCountArray[I]; 523480093f4SDimitry Andric return NumValueData; 524480093f4SDimitry Andric} 525480093f4SDimitry Andric 526480093f4SDimitry Andric/*! 527480093f4SDimitry Andric * Use this method to advance to the next \c This \c ValueProfRecord. 528480093f4SDimitry Andric */ 529480093f4SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 530480093f4SDimitry AndricValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { 531480093f4SDimitry Andric uint32_t NumValueData = getValueProfRecordNumValueData(This); 532480093f4SDimitry Andric return (ValueProfRecord *)((char *)This + 533480093f4SDimitry Andric getValueProfRecordSize(This->NumValueSites, 534480093f4SDimitry Andric NumValueData)); 535480093f4SDimitry Andric} 536480093f4SDimitry Andric 537480093f4SDimitry Andric/*! 538480093f4SDimitry Andric * Return the first \c ValueProfRecord instance. 539480093f4SDimitry Andric */ 540480093f4SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 541480093f4SDimitry AndricValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { 542480093f4SDimitry Andric return (ValueProfRecord *)((char *)This + sizeof(ValueProfData)); 543480093f4SDimitry Andric} 544480093f4SDimitry Andric 545480093f4SDimitry Andric/* Closure based interfaces. */ 546480093f4SDimitry Andric 547480093f4SDimitry Andric/*! 548480093f4SDimitry Andric * Return the total size in bytes of the on-disk value profile data 549480093f4SDimitry Andric * given the data stored in Record. 550480093f4SDimitry Andric */ 551480093f4SDimitry AndricINSTR_PROF_VISIBILITY uint32_t 552480093f4SDimitry AndricgetValueProfDataSize(ValueProfRecordClosure *Closure) { 553480093f4SDimitry Andric uint32_t Kind; 554480093f4SDimitry Andric uint32_t TotalSize = sizeof(ValueProfData); 555480093f4SDimitry Andric const void *Record = Closure->Record; 556480093f4SDimitry Andric 557480093f4SDimitry Andric for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { 558480093f4SDimitry Andric uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind); 559480093f4SDimitry Andric if (!NumValueSites) 560480093f4SDimitry Andric continue; 561480093f4SDimitry Andric TotalSize += getValueProfRecordSize(NumValueSites, 562480093f4SDimitry Andric Closure->GetNumValueData(Record, Kind)); 563480093f4SDimitry Andric } 564480093f4SDimitry Andric return TotalSize; 565480093f4SDimitry Andric} 566480093f4SDimitry Andric 567480093f4SDimitry Andric/*! 568480093f4SDimitry Andric * Extract value profile data of a function for the profile kind \c ValueKind 569480093f4SDimitry Andric * from the \c Closure and serialize the data into \c This record instance. 570480093f4SDimitry Andric */ 571480093f4SDimitry AndricINSTR_PROF_VISIBILITY void 572480093f4SDimitry AndricserializeValueProfRecordFrom(ValueProfRecord *This, 573480093f4SDimitry Andric ValueProfRecordClosure *Closure, 574480093f4SDimitry Andric uint32_t ValueKind, uint32_t NumValueSites) { 575480093f4SDimitry Andric uint32_t S; 576480093f4SDimitry Andric const void *Record = Closure->Record; 577480093f4SDimitry Andric This->Kind = ValueKind; 578480093f4SDimitry Andric This->NumValueSites = NumValueSites; 579480093f4SDimitry Andric InstrProfValueData *DstVD = getValueProfRecordValueData(This); 580480093f4SDimitry Andric 581480093f4SDimitry Andric for (S = 0; S < NumValueSites; S++) { 582480093f4SDimitry Andric uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S); 583480093f4SDimitry Andric This->SiteCountArray[S] = ND; 584480093f4SDimitry Andric Closure->GetValueForSite(Record, DstVD, ValueKind, S); 585480093f4SDimitry Andric DstVD += ND; 586480093f4SDimitry Andric } 587480093f4SDimitry Andric} 588480093f4SDimitry Andric 589480093f4SDimitry Andric/*! 590480093f4SDimitry Andric * Extract value profile data of a function from the \c Closure 591480093f4SDimitry Andric * and serialize the data into \c DstData if it is not NULL or heap 592480093f4SDimitry Andric * memory allocated by the \c Closure's allocator method. If \c 593480093f4SDimitry Andric * DstData is not null, the caller is expected to set the TotalSize 594480093f4SDimitry Andric * in DstData. 595480093f4SDimitry Andric */ 596480093f4SDimitry AndricINSTR_PROF_VISIBILITY ValueProfData * 597480093f4SDimitry AndricserializeValueProfDataFrom(ValueProfRecordClosure *Closure, 598480093f4SDimitry Andric ValueProfData *DstData) { 599480093f4SDimitry Andric uint32_t Kind; 600480093f4SDimitry Andric uint32_t TotalSize = 601480093f4SDimitry Andric DstData ? DstData->TotalSize : getValueProfDataSize(Closure); 602480093f4SDimitry Andric 603480093f4SDimitry Andric ValueProfData *VPD = 604480093f4SDimitry Andric DstData ? DstData : Closure->AllocValueProfData(TotalSize); 605480093f4SDimitry Andric 606480093f4SDimitry Andric VPD->TotalSize = TotalSize; 607480093f4SDimitry Andric VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record); 608480093f4SDimitry Andric ValueProfRecord *VR = getFirstValueProfRecord(VPD); 609480093f4SDimitry Andric for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { 610480093f4SDimitry Andric uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind); 611480093f4SDimitry Andric if (!NumValueSites) 612480093f4SDimitry Andric continue; 613480093f4SDimitry Andric serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites); 614480093f4SDimitry Andric VR = getValueProfRecordNext(VR); 615480093f4SDimitry Andric } 616480093f4SDimitry Andric return VPD; 617480093f4SDimitry Andric} 618480093f4SDimitry Andric 619480093f4SDimitry Andric#undef INSTR_PROF_COMMON_API_IMPL 620480093f4SDimitry Andric#endif /* INSTR_PROF_COMMON_API_IMPL */ 621480093f4SDimitry Andric 622480093f4SDimitry Andric/*============================================================================*/ 623480093f4SDimitry Andric 624480093f4SDimitry Andric#ifndef INSTR_PROF_DATA_DEFINED 625480093f4SDimitry Andric 626480093f4SDimitry Andric#ifndef INSTR_PROF_DATA_INC 627480093f4SDimitry Andric#define INSTR_PROF_DATA_INC 628480093f4SDimitry Andric 629480093f4SDimitry Andric/* Helper macros. */ 630480093f4SDimitry Andric#define INSTR_PROF_SIMPLE_QUOTE(x) #x 631480093f4SDimitry Andric#define INSTR_PROF_QUOTE(x) INSTR_PROF_SIMPLE_QUOTE(x) 632480093f4SDimitry Andric#define INSTR_PROF_SIMPLE_CONCAT(x,y) x ## y 633480093f4SDimitry Andric#define INSTR_PROF_CONCAT(x,y) INSTR_PROF_SIMPLE_CONCAT(x,y) 634480093f4SDimitry Andric 635480093f4SDimitry Andric/* Magic number to detect file format and endianness. 636480093f4SDimitry Andric * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, 637480093f4SDimitry Andric * so that utilities, like strings, don't grab it as a string. 129 is also 638480093f4SDimitry Andric * invalid UTF-8, and high enough to be interesting. 639480093f4SDimitry Andric * Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR" 640480093f4SDimitry Andric * for 32-bit platforms. 641480093f4SDimitry Andric */ 642480093f4SDimitry Andric#define INSTR_PROF_RAW_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ 643480093f4SDimitry Andric (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ 644480093f4SDimitry Andric (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129 645480093f4SDimitry Andric#define INSTR_PROF_RAW_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ 646480093f4SDimitry Andric (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ 647480093f4SDimitry Andric (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 648480093f4SDimitry Andric 64904eeddc0SDimitry Andric/* FIXME: Please remedy the fixme in the header before bumping the version. */ 650480093f4SDimitry Andric/* Raw profile format version (start from 1). */ 651349cc55cSDimitry Andric#define INSTR_PROF_RAW_VERSION 8 652480093f4SDimitry Andric/* Indexed profile format version (start from 1). */ 653e8d8bef9SDimitry Andric#define INSTR_PROF_INDEX_VERSION 7 6545ffd83dbSDimitry Andric/* Coverage mapping format version (start from 0). */ 655fe6060f1SDimitry Andric#define INSTR_PROF_COVMAP_VERSION 5 656480093f4SDimitry Andric 657480093f4SDimitry Andric/* Profile version is always of type uint64_t. Reserve the upper 8 bits in the 658480093f4SDimitry Andric * version for other variants of profile. We set the lowest bit of the upper 8 6590eae32dcSDimitry Andric * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation 660480093f4SDimitry Andric * generated profile, and 0 if this is a Clang FE generated profile. 661480093f4SDimitry Andric * 1 in bit 57 indicates there are context-sensitive records in the profile. 6620eae32dcSDimitry Andric * The 59th bit indicates whether to use debug info to correlate profiles. 663*1fd87a68SDimitry Andric * The 60th bit indicates single byte coverage instrumentation. 664*1fd87a68SDimitry Andric * The 61st bit indicates function entry instrumentation only. 665480093f4SDimitry Andric */ 666480093f4SDimitry Andric#define VARIANT_MASKS_ALL 0xff00000000000000ULL 667480093f4SDimitry Andric#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) 668480093f4SDimitry Andric#define VARIANT_MASK_IR_PROF (0x1ULL << 56) 669480093f4SDimitry Andric#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57) 670e8d8bef9SDimitry Andric#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58) 6710eae32dcSDimitry Andric#define VARIANT_MASK_DBG_CORRELATE (0x1ULL << 59) 672*1fd87a68SDimitry Andric#define VARIANT_MASK_BYTE_COVERAGE (0x1ULL << 60) 673*1fd87a68SDimitry Andric#define VARIANT_MASK_FUNCTION_ENTRY_ONLY (0x1ULL << 61) 674480093f4SDimitry Andric#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version 675480093f4SDimitry Andric#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime 676fe6060f1SDimitry Andric#define INSTR_PROF_PROFILE_COUNTER_BIAS_VAR __llvm_profile_counter_bias 677480093f4SDimitry Andric 678480093f4SDimitry Andric/* The variable that holds the name of the profile data 679480093f4SDimitry Andric * specified via command line. */ 680480093f4SDimitry Andric#define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename 681480093f4SDimitry Andric 682480093f4SDimitry Andric/* section name strings common to all targets other 683480093f4SDimitry Andric than WIN32 */ 684480093f4SDimitry Andric#define INSTR_PROF_DATA_COMMON __llvm_prf_data 685480093f4SDimitry Andric#define INSTR_PROF_NAME_COMMON __llvm_prf_names 686480093f4SDimitry Andric#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts 687480093f4SDimitry Andric#define INSTR_PROF_VALS_COMMON __llvm_prf_vals 688480093f4SDimitry Andric#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds 689480093f4SDimitry Andric#define INSTR_PROF_COVMAP_COMMON __llvm_covmap 6905ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_COMMON __llvm_covfun 691480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile 692480093f4SDimitry Andric/* Windows section names. Because these section names contain dollar characters, 693480093f4SDimitry Andric * they must be quoted. 694480093f4SDimitry Andric */ 695480093f4SDimitry Andric#define INSTR_PROF_DATA_COFF ".lprfd$M" 696480093f4SDimitry Andric#define INSTR_PROF_NAME_COFF ".lprfn$M" 697480093f4SDimitry Andric#define INSTR_PROF_CNTS_COFF ".lprfc$M" 698480093f4SDimitry Andric#define INSTR_PROF_VALS_COFF ".lprfv$M" 699480093f4SDimitry Andric#define INSTR_PROF_VNODES_COFF ".lprfnd$M" 700480093f4SDimitry Andric#define INSTR_PROF_COVMAP_COFF ".lcovmap$M" 7015ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_COFF ".lcovfun$M" 702480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" 703480093f4SDimitry Andric 704480093f4SDimitry Andric#ifdef _WIN32 705480093f4SDimitry Andric/* Runtime section names and name strings. */ 706480093f4SDimitry Andric#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF 707480093f4SDimitry Andric#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF 708480093f4SDimitry Andric#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF 709480093f4SDimitry Andric/* Array of pointers. Each pointer points to a list 710480093f4SDimitry Andric * of value nodes associated with one value site. 711480093f4SDimitry Andric */ 712480093f4SDimitry Andric#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF 713480093f4SDimitry Andric/* Value profile nodes section. */ 714480093f4SDimitry Andric#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF 715480093f4SDimitry Andric#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF 7165ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_SECT_NAME INSTR_PROF_COVFUN_COFF 717480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF 718480093f4SDimitry Andric#else 719480093f4SDimitry Andric/* Runtime section names and name strings. */ 720480093f4SDimitry Andric#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON) 721480093f4SDimitry Andric#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON) 722480093f4SDimitry Andric#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON) 723480093f4SDimitry Andric/* Array of pointers. Each pointer points to a list 724480093f4SDimitry Andric * of value nodes associated with one value site. 725480093f4SDimitry Andric */ 726480093f4SDimitry Andric#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON) 727480093f4SDimitry Andric/* Value profile nodes section. */ 728480093f4SDimitry Andric#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON) 729480093f4SDimitry Andric#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON) 7305ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVFUN_COMMON) 731480093f4SDimitry Andric/* Order file instrumentation. */ 732480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_SECT_NAME \ 733480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON) 734480093f4SDimitry Andric#endif 735480093f4SDimitry Andric 736480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer 737480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_NAME_STR \ 738480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_NAME) 739480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME _llvm_order_file_buffer_idx 740480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR \ 741480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME) 742480093f4SDimitry Andric 743480093f4SDimitry Andric/* Macros to define start/stop section symbol for a given 744480093f4SDimitry Andric * section on Linux. For instance 745480093f4SDimitry Andric * INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will 746480093f4SDimitry Andric * expand to __start___llvm_prof_data 747480093f4SDimitry Andric */ 748480093f4SDimitry Andric#define INSTR_PROF_SECT_START(Sect) \ 749480093f4SDimitry Andric INSTR_PROF_CONCAT(__start_,Sect) 750480093f4SDimitry Andric#define INSTR_PROF_SECT_STOP(Sect) \ 751480093f4SDimitry Andric INSTR_PROF_CONCAT(__stop_,Sect) 752480093f4SDimitry Andric 753480093f4SDimitry Andric/* Value Profiling API linkage name. */ 754480093f4SDimitry Andric#define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target 755480093f4SDimitry Andric#define INSTR_PROF_VALUE_PROF_FUNC_STR \ 756480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC) 757e8d8bef9SDimitry Andric#define INSTR_PROF_VALUE_PROF_MEMOP_FUNC __llvm_profile_instrument_memop 758e8d8bef9SDimitry Andric#define INSTR_PROF_VALUE_PROF_MEMOP_FUNC_STR \ 759e8d8bef9SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_MEMOP_FUNC) 760480093f4SDimitry Andric 761480093f4SDimitry Andric/* InstrProfile per-function control data alignment. */ 762480093f4SDimitry Andric#define INSTR_PROF_DATA_ALIGNMENT 8 763480093f4SDimitry Andric 764480093f4SDimitry Andric/* The data structure that represents a tracked value by the 765480093f4SDimitry Andric * value profiler. 766480093f4SDimitry Andric */ 767480093f4SDimitry Andrictypedef struct InstrProfValueData { 768480093f4SDimitry Andric /* Profiled value. */ 769480093f4SDimitry Andric uint64_t Value; 770480093f4SDimitry Andric /* Number of times the value appears in the training run. */ 771480093f4SDimitry Andric uint64_t Count; 772480093f4SDimitry Andric} InstrProfValueData; 773480093f4SDimitry Andric 774480093f4SDimitry Andric#endif /* INSTR_PROF_DATA_INC */ 775480093f4SDimitry Andric 776480093f4SDimitry Andric#ifndef INSTR_ORDER_FILE_INC 777480093f4SDimitry Andric/* The maximal # of functions: 128*1024 (the buffer size will be 128*4 KB). */ 778480093f4SDimitry Andric#define INSTR_ORDER_FILE_BUFFER_SIZE 131072 779480093f4SDimitry Andric#define INSTR_ORDER_FILE_BUFFER_BITS 17 780480093f4SDimitry Andric#define INSTR_ORDER_FILE_BUFFER_MASK 0x1ffff 781480093f4SDimitry Andric#endif /* INSTR_ORDER_FILE_INC */ 782480093f4SDimitry Andric#else 783480093f4SDimitry Andric#undef INSTR_PROF_DATA_DEFINED 784480093f4SDimitry Andric#endif 7855ffd83dbSDimitry Andric 7865ffd83dbSDimitry Andric#undef COVMAP_V2_OR_V3 787e8d8bef9SDimitry Andric 788e8d8bef9SDimitry Andric#ifdef INSTR_PROF_VALUE_PROF_MEMOP_API 789e8d8bef9SDimitry Andric 790e8d8bef9SDimitry Andric#ifdef __cplusplus 791e8d8bef9SDimitry Andric#define INSTR_PROF_INLINE inline 792e8d8bef9SDimitry Andric#else 793e8d8bef9SDimitry Andric#define INSTR_PROF_INLINE 794e8d8bef9SDimitry Andric#endif 795e8d8bef9SDimitry Andric 796e8d8bef9SDimitry Andric/* The value range buckets (22 buckets) for the memop size value profiling looks 797e8d8bef9SDimitry Andric * like: 798e8d8bef9SDimitry Andric * 799e8d8bef9SDimitry Andric * [0, 0] 800e8d8bef9SDimitry Andric * [1, 1] 801e8d8bef9SDimitry Andric * [2, 2] 802e8d8bef9SDimitry Andric * [3, 3] 803e8d8bef9SDimitry Andric * [4, 4] 804e8d8bef9SDimitry Andric * [5, 5] 805e8d8bef9SDimitry Andric * [6, 6] 806e8d8bef9SDimitry Andric * [7, 7] 807e8d8bef9SDimitry Andric * [8, 8] 808e8d8bef9SDimitry Andric * [9, 15] 809e8d8bef9SDimitry Andric * [16, 16] 810e8d8bef9SDimitry Andric * [17, 31] 811e8d8bef9SDimitry Andric * [32, 32] 812e8d8bef9SDimitry Andric * [33, 63] 813e8d8bef9SDimitry Andric * [64, 64] 814e8d8bef9SDimitry Andric * [65, 127] 815e8d8bef9SDimitry Andric * [128, 128] 816e8d8bef9SDimitry Andric * [129, 255] 817e8d8bef9SDimitry Andric * [256, 256] 818e8d8bef9SDimitry Andric * [257, 511] 819e8d8bef9SDimitry Andric * [512, 512] 820e8d8bef9SDimitry Andric * [513, UINT64_MAX] 821e8d8bef9SDimitry Andric * 822e8d8bef9SDimitry Andric * Each range has a 'representative value' which is the lower end value of the 823e8d8bef9SDimitry Andric * range and used to store in the runtime profile data records and the VP 824e8d8bef9SDimitry Andric * metadata. For example, it's 2 for [2, 2] and 64 for [65, 127]. 825e8d8bef9SDimitry Andric */ 826fe6060f1SDimitry Andric#define INSTR_PROF_NUM_BUCKETS 22 827e8d8bef9SDimitry Andric 828e8d8bef9SDimitry Andric/* 829e8d8bef9SDimitry Andric * Clz and Popcount. This code was copied from 830e8d8bef9SDimitry Andric * compiler-rt/lib/fuzzer/{FuzzerBuiltins.h,FuzzerBuiltinsMsvc.h} and 831e8d8bef9SDimitry Andric * llvm/include/llvm/Support/MathExtras.h. 832e8d8bef9SDimitry Andric */ 833e8d8bef9SDimitry Andric#if defined(_MSC_VER) && !defined(__clang__) 834e8d8bef9SDimitry Andric 835e8d8bef9SDimitry Andric#include <intrin.h> 836e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 837e8d8bef9SDimitry Andricint InstProfClzll(unsigned long long X) { 838e8d8bef9SDimitry Andric unsigned long LeadZeroIdx = 0; 839e8d8bef9SDimitry Andric#if !defined(_M_ARM64) && !defined(_M_X64) 840e8d8bef9SDimitry Andric // Scan the high 32 bits. 841e8d8bef9SDimitry Andric if (_BitScanReverse(&LeadZeroIdx, (unsigned long)(X >> 32))) 842e8d8bef9SDimitry Andric return (int)(63 - (LeadZeroIdx + 32)); // Create a bit offset 843e8d8bef9SDimitry Andric // from the MSB. 844e8d8bef9SDimitry Andric // Scan the low 32 bits. 845e8d8bef9SDimitry Andric if (_BitScanReverse(&LeadZeroIdx, (unsigned long)(X))) 846e8d8bef9SDimitry Andric return (int)(63 - LeadZeroIdx); 847e8d8bef9SDimitry Andric#else 848e8d8bef9SDimitry Andric if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; 849e8d8bef9SDimitry Andric#endif 850e8d8bef9SDimitry Andric return 64; 851e8d8bef9SDimitry Andric} 852e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 853e8d8bef9SDimitry Andricint InstProfPopcountll(unsigned long long X) { 854e8d8bef9SDimitry Andric // This code originates from https://reviews.llvm.org/rG30626254510f. 855e8d8bef9SDimitry Andric unsigned long long v = X; 856e8d8bef9SDimitry Andric v = v - ((v >> 1) & 0x5555555555555555ULL); 857e8d8bef9SDimitry Andric v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 858e8d8bef9SDimitry Andric v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 859e8d8bef9SDimitry Andric return (int)((unsigned long long)(v * 0x0101010101010101ULL) >> 56); 860e8d8bef9SDimitry Andric} 861e8d8bef9SDimitry Andric 862e8d8bef9SDimitry Andric#else 863e8d8bef9SDimitry Andric 864e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 865e8d8bef9SDimitry Andricint InstProfClzll(unsigned long long X) { return __builtin_clzll(X); } 866e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 867e8d8bef9SDimitry Andricint InstProfPopcountll(unsigned long long X) { return __builtin_popcountll(X); } 868e8d8bef9SDimitry Andric 869e8d8bef9SDimitry Andric#endif /* defined(_MSC_VER) && !defined(__clang__) */ 870e8d8bef9SDimitry Andric 871e8d8bef9SDimitry Andric/* Map an (observed) memop size value to the representative value of its range. 872e8d8bef9SDimitry Andric * For example, 5 -> 5, 22 -> 17, 99 -> 65, 256 -> 256, 1001 -> 513. */ 873e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint64_t 874e8d8bef9SDimitry AndricInstrProfGetRangeRepValue(uint64_t Value) { 875e8d8bef9SDimitry Andric if (Value <= 8) 876e8d8bef9SDimitry Andric // The first ranges are individually tracked. Use the value as is. 877e8d8bef9SDimitry Andric return Value; 878e8d8bef9SDimitry Andric else if (Value >= 513) 879e8d8bef9SDimitry Andric // The last range is mapped to its lowest value. 880e8d8bef9SDimitry Andric return 513; 881e8d8bef9SDimitry Andric else if (InstProfPopcountll(Value) == 1) 882e8d8bef9SDimitry Andric // If it's a power of two, use it as is. 883e8d8bef9SDimitry Andric return Value; 884e8d8bef9SDimitry Andric else 885e8d8bef9SDimitry Andric // Otherwise, take to the previous power of two + 1. 886fe6060f1SDimitry Andric return (UINT64_C(1) << (64 - InstProfClzll(Value) - 1)) + 1; 887e8d8bef9SDimitry Andric} 888e8d8bef9SDimitry Andric 889e8d8bef9SDimitry Andric/* Return true if the range that an (observed) memop size value belongs to has 890e8d8bef9SDimitry Andric * only a single value in the range. For example, 0 -> true, 8 -> true, 10 -> 891e8d8bef9SDimitry Andric * false, 64 -> true, 100 -> false, 513 -> false. */ 892e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE unsigned 893e8d8bef9SDimitry AndricInstrProfIsSingleValRange(uint64_t Value) { 894e8d8bef9SDimitry Andric if (Value <= 8) 895e8d8bef9SDimitry Andric // The first ranges are individually tracked. 896e8d8bef9SDimitry Andric return 1; 897e8d8bef9SDimitry Andric else if (InstProfPopcountll(Value) == 1) 898e8d8bef9SDimitry Andric // If it's a power of two, there's only one value. 899e8d8bef9SDimitry Andric return 1; 900e8d8bef9SDimitry Andric else 901e8d8bef9SDimitry Andric // Otherwise, there's more than one value in the range. 902e8d8bef9SDimitry Andric return 0; 903e8d8bef9SDimitry Andric} 904e8d8bef9SDimitry Andric 905e8d8bef9SDimitry Andric#endif /* INSTR_PROF_VALUE_PROF_MEMOP_API */ 906