| /*===-- InstrProfData.inc - instr profiling runtime structures -----------=== *\ |
| |* |
| |* The LLVM Compiler Infrastructure |
| |* |
| |* This file is distributed under the University of Illinois Open Source |
| |* License. See LICENSE.TXT for details. |
| |* |
| \*===----------------------------------------------------------------------===*/ |
| /* |
| * This is the master file that defines all the data structure, signature, |
| * constant literals that are shared across profiling runtime library, |
| * compiler (instrumentation), and host tools (reader/writer). The entities |
| * defined in this file affect the profile runtime ABI, the raw profile format, |
| * or both. |
| * |
| * The file has two identical copies. The master copy lives in LLVM and |
| * the other one sits in compiler-rt/lib/profile directory. To make changes |
| * in this file, first modify the master copy and copy it over to compiler-rt. |
| * Testing of any change in this file can start only after the two copies are |
| * synced up. |
| * |
| * The first part of the file includes macros that defines types, names, and |
| * initializers for the member fields of the core data structures. The field |
| * declarations for one structure is enabled by defining the field activation |
| * macro associated with that structure. Only one field activation record |
| * can be defined at one time and the rest definitions will be filtered out by |
| * the preprocessor. |
| * |
| * Examples of how the template is used to instantiate structure definition: |
| * 1. To declare a structure: |
| * |
| * struct ProfData { |
| * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ |
| * Type Name; |
| * #include "llvm/ProfileData/InstrProfData.inc" |
| * }; |
| * |
| * 2. To construct LLVM type arrays for the struct type: |
| * |
| * Type *DataTypes[] = { |
| * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ |
| * LLVMType, |
| * #include "llvm/ProfileData/InstrProfData.inc" |
| * }; |
| * |
| * 4. To construct constant array for the initializers: |
| * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ |
| * Initializer, |
| * Constant *ConstantVals[] = { |
| * #include "llvm/ProfileData/InstrProfData.inc" |
| * }; |
| * |
| * |
| * The second part of the file includes definitions all other entities that |
| * are related to runtime ABI and format. When no field activation macro is |
| * defined, this file can be included to introduce the definitions. |
| * |
| \*===----------------------------------------------------------------------===*/ |
| |
| /* INSTR_PROF_DATA start. */ |
| /* Definition of member fields of the per-function control structure. */ |
| #ifndef INSTR_PROF_DATA |
| #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) |
| #else |
| #define INSTR_PROF_DATA_DEFINED |
| #endif |
| |
| INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ |
| ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \ |
| NamePtr->getType()->getPointerElementType()->getArrayNumElements())) |
| INSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \ |
| ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters)) |
| INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ |
| ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ |
| Inc->getHash()->getZExtValue())) |
| INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), NamePtr, \ |
| ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx))) |
| INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt64PtrTy(Ctx), CounterPtr, \ |
| ConstantExpr::getBitCast(CounterPtr, \ |
| llvm::Type::getInt64PtrTy(Ctx))) |
| INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \ |
| FunctionAddr) |
| INSTR_PROF_DATA(IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \ |
| ConstantPointerNull::get(Int8PtrTy)) |
| INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \ |
| ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) |
| #undef INSTR_PROF_DATA |
| /* INSTR_PROF_DATA end. */ |
| |
| /* INSTR_PROF_RAW_HEADER start */ |
| /* Definition of member fields of the raw profile header data structure. */ |
| #ifndef INSTR_PROF_RAW_HEADER |
| #define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) |
| #else |
| #define INSTR_PROF_DATA_DEFINED |
| #endif |
| INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic()) |
| INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version()) |
| INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize) |
| INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize) |
| INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize) |
| INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) |
| INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) |
| INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) |
| INSTR_PROF_RAW_HEADER(uint64_t, ValueDataSize, ValueDataSize) |
| INSTR_PROF_RAW_HEADER(uint64_t, ValueDataDelta, (uintptr_t)ValueDataBegin) |
| #undef INSTR_PROF_RAW_HEADER |
| /* INSTR_PROF_RAW_HEADER end */ |
| |
| /* VALUE_PROF_FUNC_PARAM start */ |
| /* Definition of parameter types of the runtime API used to do value profiling |
| * for a given value site. |
| */ |
| #ifndef VALUE_PROF_FUNC_PARAM |
| #define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) |
| #define INSTR_PROF_COMMA |
| #else |
| #define INSTR_PROF_DATA_DEFINED |
| #define INSTR_PROF_COMMA , |
| #endif |
| VALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \ |
| INSTR_PROF_COMMA |
| VALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA |
| VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) |
| #undef VALUE_PROF_FUNC_PARAM |
| #undef INSTR_PROF_COMMA |
| /* VALUE_PROF_FUNC_PARAM end */ |
| |
| /* VALUE_PROF_KIND start */ |
| #ifndef VALUE_PROF_KIND |
| #define VALUE_PROF_KIND(Enumerator, Value) |
| #else |
| #define INSTR_PROF_DATA_DEFINED |
| #endif |
| VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0) |
| /* These two kinds must be the last to be |
| * declared. This is to make sure the string |
| * array created with the template can be |
| * indexed with the kind value. |
| */ |
| VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget) |
| VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget) |
| |
| #undef VALUE_PROF_KIND |
| /* VALUE_PROF_KIND end */ |
| |
| /* COVMAP_FUNC_RECORD start */ |
| /* Definition of member fields of the function record structure in coverage |
| * map. |
| */ |
| #ifndef COVMAP_FUNC_RECORD |
| #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Initializer) |
| #else |
| #define INSTR_PROF_DATA_DEFINED |
| #endif |
| COVMAP_FUNC_RECORD(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), \ |
| NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \ |
| llvm::Type::getInt8PtrTy(Ctx))) |
| COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ |
| llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\ |
| NameValue.size())) |
| COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \ |
| llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\ |
| CoverageMapping.size())) |
| COVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ |
| llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), FuncHash)) |
| #undef COVMAP_FUNC_RECORD |
| /* COVMAP_FUNC_RECORD end. */ |
| |
| |
| #ifdef INSTR_PROF_VALUE_PROF_DATA |
| #define INSTR_PROF_DATA_DEFINED |
| |
| /*! |
| * This is the header of the data structure that defines the on-disk |
| * layout of the value profile data of a particular kind for one function. |
| */ |
| typedef struct ValueProfRecord { |
| /* The kind of the value profile record. */ |
| uint32_t Kind; |
| /* |
| * The number of value profile sites. It is guaranteed to be non-zero; |
| * otherwise the record for this kind won't be emitted. |
| */ |
| uint32_t NumValueSites; |
| /* |
| * The first element of the array that stores the number of profiled |
| * values for each value site. The size of the array is NumValueSites. |
| * Since NumValueSites is greater than zero, there is at least one |
| * element in the array. |
| */ |
| uint8_t SiteCountArray[1]; |
| |
| /* |
| * The fake declaration is for documentation purpose only. |
| * Align the start of next field to be on 8 byte boundaries. |
| uint8_t Padding[X]; |
| */ |
| |
| /* The array of value profile data. The size of the array is the sum |
| * of all elements in SiteCountArray[]. |
| InstrProfValueData ValueData[]; |
| */ |
| |
| #ifdef __cplusplus |
| /*! |
| * \brief Return the number of value sites. |
| */ |
| uint32_t getNumValueSites() const { return NumValueSites; } |
| /*! |
| * \brief Read data from this record and save it to Record. |
| */ |
| void deserializeTo(InstrProfRecord &Record, |
| InstrProfRecord::ValueMapType *VMap); |
| /* |
| * In-place byte swap: |
| * Do byte swap for this instance. \c Old is the original order before |
| * the swap, and \c New is the New byte order. |
| */ |
| void swapBytes(support::endianness Old, support::endianness New); |
| #endif |
| } ValueProfRecord; |
| |
| /*! |
| * Per-function header/control data structure for value profiling |
| * data in indexed format. |
| */ |
| typedef struct ValueProfData { |
| /* |
| * Total size in bytes including this field. It must be a multiple |
| * of sizeof(uint64_t). |
| */ |
| uint32_t TotalSize; |
| /* |
| *The number of value profile kinds that has value profile data. |
| * In this implementation, a value profile kind is considered to |
| * have profile data if the number of value profile sites for the |
| * kind is not zero. More aggressively, the implementation can |
| * choose to check the actual data value: if none of the value sites |
| * has any profiled values, the kind can be skipped. |
| */ |
| uint32_t NumValueKinds; |
| |
| /* |
| * Following are a sequence of variable length records. The prefix/header |
| * of each record is defined by ValueProfRecord type. The number of |
| * records is NumValueKinds. |
| * ValueProfRecord Record_1; |
| * ValueProfRecord Record_N; |
| */ |
| |
| #if __cplusplus |
| /*! |
| * Return the total size in bytes of the on-disk value profile data |
| * given the data stored in Record. |
| */ |
| static uint32_t getSize(const InstrProfRecord &Record); |
| /*! |
| * Return a pointer to \c ValueProfData instance ready to be streamed. |
| */ |
| static std::unique_ptr<ValueProfData> |
| serializeFrom(const InstrProfRecord &Record); |
| /*! |
| * Check the integrity of the record. Return the error code when |
| * an error is detected, otherwise return instrprof_error::success. |
| */ |
| instrprof_error checkIntegrity(); |
| /*! |
| * Return a pointer to \c ValueProfileData instance ready to be read. |
| * All data in the instance are properly byte swapped. The input |
| * data is assumed to be in little endian order. |
| */ |
| static ErrorOr<std::unique_ptr<ValueProfData>> |
| getValueProfData(const unsigned char *SrcBuffer, |
| const unsigned char *const SrcBufferEnd, |
| support::endianness SrcDataEndianness); |
| /*! |
| * Swap byte order from \c Endianness order to host byte order. |
| */ |
| void swapBytesToHost(support::endianness Endianness); |
| /*! |
| * Swap byte order from host byte order to \c Endianness order. |
| */ |
| void swapBytesFromHost(support::endianness Endianness); |
| /*! |
| * Return the total size of \c ValueProfileData. |
| */ |
| uint32_t getSize() const { return TotalSize; } |
| /*! |
| * Read data from this data and save it to \c Record. |
| */ |
| void deserializeTo(InstrProfRecord &Record, |
| InstrProfRecord::ValueMapType *VMap); |
| void operator delete(void *ptr) { ::operator delete(ptr); } |
| #endif |
| } ValueProfData; |
| |
| /* |
| * The closure is designed to abstact away two types of value profile data: |
| * - InstrProfRecord which is the primary data structure used to |
| * represent profile data in host tools (reader, writer, and profile-use) |
| * - value profile runtime data structure suitable to be used by C |
| * runtime library. |
| * |
| * Both sources of data need to serialize to disk/memory-buffer in common |
| * format: ValueProfData. The abstraction allows compiler-rt's raw profiler |
| * writer to share the same format and code with indexed profile writer. |
| * |
| * For documentation of the member methods below, refer to corresponding methods |
| * in class InstrProfRecord. |
| */ |
| typedef struct ValueProfRecordClosure { |
| const void *Record; |
| uint32_t (*GetNumValueKinds)(const void *Record); |
| uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind); |
| uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind); |
| uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S); |
| |
| /* |
| * After extracting the value profile data from the value profile record, |
| * this method is used to map the in-memory value to on-disk value. If |
| * the method is null, value will be written out untranslated. |
| */ |
| uint64_t (*RemapValueData)(uint32_t, uint64_t Value); |
| void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K, |
| uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)); |
| ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes); |
| } ValueProfRecordClosure; |
| |
| /* |
| * A wrapper struct that represents value profile runtime data. |
| * Like InstrProfRecord class which is used by profiling host tools, |
| * ValueProfRuntimeRecord also implements the abstract intefaces defined in |
| * ValueProfRecordClosure so that the runtime data can be serialized using |
| * shared C implementation. In this structure, NumValueSites and Nodes |
| * members are the primary fields while other fields hold the derived |
| * information for fast implementation of closure interfaces. |
| */ |
| typedef struct ValueProfRuntimeRecord { |
| /* Number of sites for each value profile kind. */ |
| const uint16_t *NumValueSites; |
| /* An array of linked-list headers. The size of of the array is the |
| * total number of value profile sites : sum(NumValueSites[*])). Each |
| * linked-list stores the values profiled for a value profile site. */ |
| ValueProfNode **Nodes; |
| |
| /* Total number of value profile kinds which have at least one |
| * value profile sites. */ |
| uint32_t NumValueKinds; |
| /* An array recording the number of values tracked at each site. |
| * The size of the array is TotalNumValueSites. */ |
| uint8_t *SiteCountArray[IPVK_Last + 1]; |
| ValueProfNode **NodesKind[IPVK_Last + 1]; |
| } ValueProfRuntimeRecord; |
| |
| /* Forward declarations of C interfaces. */ |
| int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, |
| const uint16_t *NumValueSites, |
| ValueProfNode **Nodes); |
| void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord); |
| uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record); |
| ValueProfData * |
| serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record, |
| ValueProfData *Dst); |
| uint32_t getNumValueKindsRT(const void *R); |
| |
| #undef INSTR_PROF_VALUE_PROF_DATA |
| #endif /* INSTR_PROF_VALUE_PROF_DATA */ |
| |
| |
| #ifdef INSTR_PROF_COMMON_API_IMPL |
| #define INSTR_PROF_DATA_DEFINED |
| #ifdef __cplusplus |
| #define INSTR_PROF_INLINE inline |
| #else |
| #define INSTR_PROF_INLINE |
| #endif |
| |
| #ifndef offsetof |
| #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
| #endif |
| |
| /*! |
| * \brief Return the \c ValueProfRecord header size including the |
| * padding bytes. |
| */ |
| INSTR_PROF_INLINE |
| uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) { |
| uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) + |
| sizeof(uint8_t) * NumValueSites; |
| /* Round the size to multiple of 8 bytes. */ |
| Size = (Size + 7) & ~7; |
| return Size; |
| } |
| |
| /*! |
| * \brief Return the total size of the value profile record including the |
| * header and the value data. |
| */ |
| INSTR_PROF_INLINE |
| uint32_t getValueProfRecordSize(uint32_t NumValueSites, |
| uint32_t NumValueData) { |
| return getValueProfRecordHeaderSize(NumValueSites) + |
| sizeof(InstrProfValueData) * NumValueData; |
| } |
| |
| /*! |
| * \brief Return the pointer to the start of value data array. |
| */ |
| INSTR_PROF_INLINE |
| InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { |
| return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize( |
| This->NumValueSites)); |
| } |
| |
| /*! |
| * \brief Return the total number of value data for \c This record. |
| */ |
| INSTR_PROF_INLINE |
| uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { |
| uint32_t NumValueData = 0; |
| uint32_t I; |
| for (I = 0; I < This->NumValueSites; I++) |
| NumValueData += This->SiteCountArray[I]; |
| return NumValueData; |
| } |
| |
| /*! |
| * \brief Use this method to advance to the next \c This \c ValueProfRecord. |
| */ |
| INSTR_PROF_INLINE |
| ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { |
| uint32_t NumValueData = getValueProfRecordNumValueData(This); |
| return (ValueProfRecord *)((char *)This + |
| getValueProfRecordSize(This->NumValueSites, |
| NumValueData)); |
| } |
| |
| /*! |
| * \brief Return the first \c ValueProfRecord instance. |
| */ |
| INSTR_PROF_INLINE |
| ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { |
| return (ValueProfRecord *)((char *)This + sizeof(ValueProfData)); |
| } |
| |
| /* Closure based interfaces. */ |
| |
| /*! |
| * Return the total size in bytes of the on-disk value profile data |
| * given the data stored in Record. |
| */ |
| uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) { |
| uint32_t Kind; |
| uint32_t TotalSize = sizeof(ValueProfData); |
| const void *Record = Closure->Record; |
| uint32_t NumValueKinds = Closure->GetNumValueKinds(Record); |
| if (NumValueKinds == 0) |
| return TotalSize; |
| |
| for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { |
| uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind); |
| if (!NumValueSites) |
| continue; |
| TotalSize += getValueProfRecordSize(NumValueSites, |
| Closure->GetNumValueData(Record, Kind)); |
| } |
| return TotalSize; |
| } |
| |
| /*! |
| * Extract value profile data of a function for the profile kind \c ValueKind |
| * from the \c Closure and serialize the data into \c This record instance. |
| */ |
| void serializeValueProfRecordFrom(ValueProfRecord *This, |
| ValueProfRecordClosure *Closure, |
| uint32_t ValueKind, uint32_t NumValueSites) { |
| uint32_t S; |
| const void *Record = Closure->Record; |
| This->Kind = ValueKind; |
| This->NumValueSites = NumValueSites; |
| InstrProfValueData *DstVD = getValueProfRecordValueData(This); |
| |
| for (S = 0; S < NumValueSites; S++) { |
| uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S); |
| This->SiteCountArray[S] = ND; |
| Closure->GetValueForSite(Record, DstVD, ValueKind, S, |
| Closure->RemapValueData); |
| DstVD += ND; |
| } |
| } |
| |
| /*! |
| * Extract value profile data of a function from the \c Closure |
| * and serialize the data into \c DstData if it is not NULL or heap |
| * memory allocated by the \c Closure's allocator method. |
| */ |
| ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure, |
| ValueProfData *DstData) { |
| uint32_t Kind; |
| uint32_t TotalSize = getValueProfDataSize(Closure); |
| |
| ValueProfData *VPD = |
| DstData ? DstData : Closure->AllocValueProfData(TotalSize); |
| |
| VPD->TotalSize = TotalSize; |
| VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record); |
| ValueProfRecord *VR = getFirstValueProfRecord(VPD); |
| for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { |
| uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind); |
| if (!NumValueSites) |
| continue; |
| serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites); |
| VR = getValueProfRecordNext(VR); |
| } |
| return VPD; |
| } |
| |
| /* |
| * The value profiler runtime library stores the value profile data |
| * for a given function in \c NumValueSites and \c Nodes structures. |
| * \c ValueProfRuntimeRecord class is used to encapsulate the runtime |
| * profile data and provides fast interfaces to retrieve the profile |
| * information. This interface is used to initialize the runtime record |
| * and pre-compute the information needed for efficient implementation |
| * of callbacks required by ValueProfRecordClosure class. |
| */ |
| int initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord, |
| const uint16_t *NumValueSites, |
| ValueProfNode **Nodes) { |
| unsigned I, J, S = 0, NumValueKinds = 0; |
| RuntimeRecord->NumValueSites = NumValueSites; |
| RuntimeRecord->Nodes = Nodes; |
| for (I = 0; I <= IPVK_Last; I++) { |
| uint16_t N = NumValueSites[I]; |
| if (!N) { |
| RuntimeRecord->SiteCountArray[I] = 0; |
| continue; |
| } |
| NumValueKinds++; |
| RuntimeRecord->SiteCountArray[I] = (uint8_t *)calloc(N, 1); |
| if (!RuntimeRecord->SiteCountArray[I]) |
| return 1; |
| RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : NULL; |
| for (J = 0; J < N; J++) { |
| /* Compute value count for each site. */ |
| uint32_t C = 0; |
| ValueProfNode *Site = Nodes ? RuntimeRecord->NodesKind[I][J] : NULL; |
| while (Site) { |
| C++; |
| Site = Site->Next; |
| } |
| if (C > UCHAR_MAX) |
| C = UCHAR_MAX; |
| RuntimeRecord->SiteCountArray[I][J] = C; |
| } |
| S += N; |
| } |
| RuntimeRecord->NumValueKinds = NumValueKinds; |
| return 0; |
| } |
| |
| void finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord) { |
| unsigned I; |
| for (I = 0; I <= IPVK_Last; I++) { |
| if (RuntimeRecord->SiteCountArray[I]) |
| free(RuntimeRecord->SiteCountArray[I]); |
| } |
| } |
| |
| /* ValueProfRecordClosure Interface implementation for |
| * ValueProfDataRuntimeRecord. */ |
| uint32_t getNumValueKindsRT(const void *R) { |
| return ((const ValueProfRuntimeRecord *)R)->NumValueKinds; |
| } |
| |
| uint32_t getNumValueSitesRT(const void *R, uint32_t VK) { |
| return ((const ValueProfRuntimeRecord *)R)->NumValueSites[VK]; |
| } |
| |
| uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK, uint32_t S) { |
| const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R; |
| return Record->SiteCountArray[VK][S]; |
| } |
| |
| uint32_t getNumValueDataRT(const void *R, uint32_t VK) { |
| unsigned I, S = 0; |
| const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R; |
| if (Record->SiteCountArray[VK] == 0) |
| return 0; |
| for (I = 0; I < Record->NumValueSites[VK]; I++) |
| S += Record->SiteCountArray[VK][I]; |
| return S; |
| } |
| |
| void getValueForSiteRT(const void *R, InstrProfValueData *Dst, uint32_t VK, |
| uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t)) { |
| unsigned I, N = 0; |
| const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R; |
| N = getNumValueDataForSiteRT(R, VK, S); |
| if (N == 0) |
| return; |
| ValueProfNode *VNode = Record->NodesKind[VK][S]; |
| for (I = 0; I < N; I++) { |
| Dst[I] = VNode->VData; |
| VNode = VNode->Next; |
| } |
| } |
| |
| ValueProfData *allocValueProfDataRT(size_t TotalSizeInBytes) { |
| return (ValueProfData *)calloc(TotalSizeInBytes, 1); |
| } |
| |
| static ValueProfRecordClosure RTRecordClosure = {0, |
| getNumValueKindsRT, |
| getNumValueSitesRT, |
| getNumValueDataRT, |
| getNumValueDataForSiteRT, |
| 0, |
| getValueForSiteRT, |
| allocValueProfDataRT}; |
| |
| /* |
| * Return the size of ValueProfData structure to store data |
| * recorded in the runtime record. |
| */ |
| uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record) { |
| RTRecordClosure.Record = Record; |
| return getValueProfDataSize(&RTRecordClosure); |
| } |
| |
| /* |
| * Return a ValueProfData instance that stores the data collected |
| * from runtime. If \c DstData is provided by the caller, the value |
| * profile data will be store in *DstData and DstData is returned, |
| * otherwise the method will allocate space for the value data and |
| * return pointer to the newly allocated space. |
| */ |
| ValueProfData * |
| serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record, |
| ValueProfData *DstData) { |
| RTRecordClosure.Record = Record; |
| return serializeValueProfDataFrom(&RTRecordClosure, DstData); |
| } |
| |
| |
| #undef INSTR_PROF_COMMON_API_IMPL |
| #endif /* INSTR_PROF_COMMON_API_IMPL */ |
| |
| /*============================================================================*/ |
| |
| |
| #ifndef INSTR_PROF_DATA_DEFINED |
| |
| #ifndef INSTR_PROF_DATA_INC_ |
| #define INSTR_PROF_DATA_INC_ |
| |
| /* Helper macros. */ |
| #define INSTR_PROF_SIMPLE_QUOTE(x) #x |
| #define INSTR_PROF_QUOTE(x) INSTR_PROF_SIMPLE_QUOTE(x) |
| #define INSTR_PROF_SIMPLE_CONCAT(x,y) x ## y |
| #define INSTR_PROF_CONCAT(x,y) INSTR_PROF_SIMPLE_CONCAT(x,y) |
| |
| /* Magic number to detect file format and endianness. |
| * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, |
| * so that utilities, like strings, don't grab it as a string. 129 is also |
| * invalid UTF-8, and high enough to be interesting. |
| * Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR" |
| * for 32-bit platforms. |
| */ |
| #define INSTR_PROF_RAW_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ |
| (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ |
| (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129 |
| #define INSTR_PROF_RAW_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ |
| (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ |
| (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 |
| |
| /* Raw profile format version. */ |
| #define INSTR_PROF_RAW_VERSION 2 |
| |
| /* Runtime section names and name strings. */ |
| #define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data |
| #define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names |
| #define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts |
| |
| #define INSTR_PROF_DATA_SECT_NAME_STR \ |
| INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME) |
| #define INSTR_PROF_NAME_SECT_NAME_STR \ |
| INSTR_PROF_QUOTE(INSTR_PROF_NAME_SECT_NAME) |
| #define INSTR_PROF_CNTS_SECT_NAME_STR \ |
| INSTR_PROF_QUOTE(INSTR_PROF_CNTS_SECT_NAME) |
| |
| /* Macros to define start/stop section symbol for a given |
| * section on Linux. For instance |
| * INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will |
| * expand to __start___llvm_prof_data |
| */ |
| #define INSTR_PROF_SECT_START(Sect) \ |
| INSTR_PROF_CONCAT(__start_,Sect) |
| #define INSTR_PROF_SECT_STOP(Sect) \ |
| INSTR_PROF_CONCAT(__stop_,Sect) |
| |
| /* Value Profiling API linkage name. */ |
| #define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target |
| #define INSTR_PROF_VALUE_PROF_FUNC_STR \ |
| INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC) |
| |
| /* InstrProfile per-function control data alignment. */ |
| #define INSTR_PROF_DATA_ALIGNMENT 8 |
| |
| /* The data structure that represents a tracked value by the |
| * value profiler. |
| */ |
| typedef struct InstrProfValueData { |
| /* Profiled value. */ |
| uint64_t Value; |
| /* Number of times the value appears in the training run. */ |
| uint64_t Count; |
| } InstrProfValueData; |
| |
| /* This is an internal data structure used by value profiler. It |
| * is defined here to allow serialization code sharing by LLVM |
| * to be used in unit test. |
| */ |
| typedef struct ValueProfNode { |
| InstrProfValueData VData; |
| struct ValueProfNode *Next; |
| } ValueProfNode; |
| |
| #endif /* INSTR_PROF_DATA_INC_ */ |
| |
| #else |
| #undef INSTR_PROF_DATA_DEFINED |
| #endif |
| |