10b57cec5SDimitry Andric /*===- InstrProfiling.h- Support library for PGO instrumentation ----------===*\ 20b57cec5SDimitry Andric |* 30b57cec5SDimitry Andric |* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric |* See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric |* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric |* 70b57cec5SDimitry Andric \*===----------------------------------------------------------------------===*/ 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef PROFILE_INSTRPROFILING_INTERNALH_ 100b57cec5SDimitry Andric #define PROFILE_INSTRPROFILING_INTERNALH_ 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include <stddef.h> 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "InstrProfiling.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric /*! 170b57cec5SDimitry Andric * \brief Write instrumentation data to the given buffer, given explicit 180b57cec5SDimitry Andric * pointers to the live data in memory. This function is probably not what you 190b57cec5SDimitry Andric * want. Use __llvm_profile_get_size_for_buffer instead. Use this function if 200b57cec5SDimitry Andric * your program has a custom memory layout. 210b57cec5SDimitry Andric */ 220b57cec5SDimitry Andric uint64_t __llvm_profile_get_size_for_buffer_internal( 230b57cec5SDimitry Andric const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd, 245f757f3fSDimitry Andric const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin, 25*0fca6ea1SDimitry Andric const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd, 26*0fca6ea1SDimitry Andric const VTableProfData *VTableBegin, const VTableProfData *VTableEnd, 27*0fca6ea1SDimitry Andric const char *VNamesBegin, const char *VNamesEnd); 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /*! 300b57cec5SDimitry Andric * \brief Write instrumentation data to the given buffer, given explicit 310b57cec5SDimitry Andric * pointers to the live data in memory. This function is probably not what you 320b57cec5SDimitry Andric * want. Use __llvm_profile_write_buffer instead. Use this function if your 330b57cec5SDimitry Andric * program has a custom memory layout. 340b57cec5SDimitry Andric * 350b57cec5SDimitry Andric * \pre \c Buffer is the start of a buffer at least as big as \a 360b57cec5SDimitry Andric * __llvm_profile_get_size_for_buffer_internal(). 370b57cec5SDimitry Andric */ 380b57cec5SDimitry Andric int __llvm_profile_write_buffer_internal( 390b57cec5SDimitry Andric char *Buffer, const __llvm_profile_data *DataBegin, 4004eeddc0SDimitry Andric const __llvm_profile_data *DataEnd, const char *CountersBegin, 415f757f3fSDimitry Andric const char *CountersEnd, const char *BitmapBegin, const char *BitmapEnd, 425f757f3fSDimitry Andric const char *NamesBegin, const char *NamesEnd); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric /*! 450b57cec5SDimitry Andric * The data structure describing the data to be written by the 460b57cec5SDimitry Andric * low level writer callback function. 47480093f4SDimitry Andric * 48480093f4SDimitry Andric * If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is 49480093f4SDimitry Andric * 0, the write is skipped (the writer simply advances ElmSize*NumElm bytes). 50480093f4SDimitry Andric * 51480093f4SDimitry Andric * If \ref ProfDataIOVec.Data is null, and \ref ProfDataIOVec.UseZeroPadding is 52480093f4SDimitry Andric * nonzero, ElmSize*NumElm zero bytes are written. 530b57cec5SDimitry Andric */ 540b57cec5SDimitry Andric typedef struct ProfDataIOVec { 550b57cec5SDimitry Andric const void *Data; 560b57cec5SDimitry Andric size_t ElmSize; 570b57cec5SDimitry Andric size_t NumElm; 58480093f4SDimitry Andric int UseZeroPadding; 590b57cec5SDimitry Andric } ProfDataIOVec; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric struct ProfDataWriter; 620b57cec5SDimitry Andric typedef uint32_t (*WriterCallback)(struct ProfDataWriter *This, ProfDataIOVec *, 630b57cec5SDimitry Andric uint32_t NumIOVecs); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric typedef struct ProfDataWriter { 660b57cec5SDimitry Andric WriterCallback Write; 670b57cec5SDimitry Andric void *WriterCtx; 680b57cec5SDimitry Andric } ProfDataWriter; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric /*! 710b57cec5SDimitry Andric * The data structure for buffered IO of profile data. 720b57cec5SDimitry Andric */ 730b57cec5SDimitry Andric typedef struct ProfBufferIO { 740b57cec5SDimitry Andric ProfDataWriter *FileWriter; 750b57cec5SDimitry Andric uint32_t OwnFileWriter; 760b57cec5SDimitry Andric /* The start of the buffer. */ 770b57cec5SDimitry Andric uint8_t *BufferStart; 780b57cec5SDimitry Andric /* Total size of the buffer. */ 790b57cec5SDimitry Andric uint32_t BufferSz; 800b57cec5SDimitry Andric /* Current byte offset from the start of the buffer. */ 810b57cec5SDimitry Andric uint32_t CurOffset; 820b57cec5SDimitry Andric } ProfBufferIO; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric /* The creator interface used by testing. */ 850b57cec5SDimitry Andric ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t BufferSz); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric /*! 880b57cec5SDimitry Andric * This is the interface to create a handle for buffered IO. 890b57cec5SDimitry Andric */ 900b57cec5SDimitry Andric ProfBufferIO *lprofCreateBufferIO(ProfDataWriter *FileWriter); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /*! 930b57cec5SDimitry Andric * The interface to destroy the bufferIO handle and reclaim 940b57cec5SDimitry Andric * the memory. 950b57cec5SDimitry Andric */ 960b57cec5SDimitry Andric void lprofDeleteBufferIO(ProfBufferIO *BufferIO); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /*! 990b57cec5SDimitry Andric * This is the interface to write \c Data of \c Size bytes through 1000b57cec5SDimitry Andric * \c BufferIO. Returns 0 if successful, otherwise return -1. 1010b57cec5SDimitry Andric */ 1020b57cec5SDimitry Andric int lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, 1030b57cec5SDimitry Andric uint32_t Size); 1040b57cec5SDimitry Andric /*! 1050b57cec5SDimitry Andric * The interface to flush the remaining data in the buffer. 1060b57cec5SDimitry Andric * through the low level writer callback. 1070b57cec5SDimitry Andric */ 1080b57cec5SDimitry Andric int lprofBufferIOFlush(ProfBufferIO *BufferIO); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /* The low level interface to write data into a buffer. It is used as the 1110b57cec5SDimitry Andric * callback by other high level writer methods such as buffered IO writer 1120b57cec5SDimitry Andric * and profile data writer. */ 1130b57cec5SDimitry Andric uint32_t lprofBufferWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, 1140b57cec5SDimitry Andric uint32_t NumIOVecs); 1150b57cec5SDimitry Andric void initBufferWriter(ProfDataWriter *BufferWriter, char *Buffer); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric struct ValueProfData; 1180b57cec5SDimitry Andric struct ValueProfRecord; 1190b57cec5SDimitry Andric struct InstrProfValueData; 1200b57cec5SDimitry Andric struct ValueProfNode; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /*! 1230b57cec5SDimitry Andric * The class that defines a set of methods to read value profile 1240b57cec5SDimitry Andric * data for streaming/serialization from the instrumentation runtime. 1250b57cec5SDimitry Andric */ 1260b57cec5SDimitry Andric typedef struct VPDataReaderType { 1270b57cec5SDimitry Andric uint32_t (*InitRTRecord)(const __llvm_profile_data *Data, 1280b57cec5SDimitry Andric uint8_t *SiteCountArray[]); 1290b57cec5SDimitry Andric /* Function pointer to getValueProfRecordHeader method. */ 1300b57cec5SDimitry Andric uint32_t (*GetValueProfRecordHeaderSize)(uint32_t NumSites); 1310b57cec5SDimitry Andric /* Function pointer to getFristValueProfRecord method. */ 1320b57cec5SDimitry Andric struct ValueProfRecord *(*GetFirstValueProfRecord)(struct ValueProfData *); 1330b57cec5SDimitry Andric /* Return the number of value data for site \p Site. */ 1340b57cec5SDimitry Andric uint32_t (*GetNumValueDataForSite)(uint32_t VK, uint32_t Site); 1350b57cec5SDimitry Andric /* Return the total size of the value profile data of the 1360b57cec5SDimitry Andric * current function. */ 1370b57cec5SDimitry Andric uint32_t (*GetValueProfDataSize)(void); 1380b57cec5SDimitry Andric /*! 1390b57cec5SDimitry Andric * Read the next \p N value data for site \p Site and store the data 1400b57cec5SDimitry Andric * in \p Dst. \p StartNode is the first value node to start with if 1410b57cec5SDimitry Andric * it is not null. The function returns the pointer to the value 1420b57cec5SDimitry Andric * node pointer to be used as the \p StartNode of the next batch reading. 1430b57cec5SDimitry Andric * If there is nothing left, it returns NULL. 1440b57cec5SDimitry Andric */ 1450b57cec5SDimitry Andric struct ValueProfNode *(*GetValueData)(uint32_t ValueKind, uint32_t Site, 1460b57cec5SDimitry Andric struct InstrProfValueData *Dst, 1470b57cec5SDimitry Andric struct ValueProfNode *StartNode, 1480b57cec5SDimitry Andric uint32_t N); 1490b57cec5SDimitry Andric } VPDataReaderType; 1500b57cec5SDimitry Andric 151349cc55cSDimitry Andric /* Write profile data to destination. If SkipNameDataWrite is set to 1, 152349cc55cSDimitry Andric the name data is already in destination, we just skip over it. */ 1530b57cec5SDimitry Andric int lprofWriteData(ProfDataWriter *Writer, VPDataReaderType *VPDataReader, 1540b57cec5SDimitry Andric int SkipNameDataWrite); 1550b57cec5SDimitry Andric int lprofWriteDataImpl(ProfDataWriter *Writer, 1560b57cec5SDimitry Andric const __llvm_profile_data *DataBegin, 1570b57cec5SDimitry Andric const __llvm_profile_data *DataEnd, 15804eeddc0SDimitry Andric const char *CountersBegin, const char *CountersEnd, 1595f757f3fSDimitry Andric const char *BitmapBegin, const char *BitmapEnd, 1600b57cec5SDimitry Andric VPDataReaderType *VPDataReader, const char *NamesBegin, 161*0fca6ea1SDimitry Andric const char *NamesEnd, const VTableProfData *VTableBegin, 162*0fca6ea1SDimitry Andric const VTableProfData *VTableEnd, const char *VNamesBegin, 163*0fca6ea1SDimitry Andric const char *VNamesEnd, int SkipNameDataWrite); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric /* Merge value profile data pointed to by SrcValueProfData into 1660b57cec5SDimitry Andric * in-memory profile counters pointed by to DstData. */ 1670b57cec5SDimitry Andric void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData, 1680b57cec5SDimitry Andric __llvm_profile_data *DstData); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric VPDataReaderType *lprofGetVPDataReader(); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /* Internal interface used by test to reset the max number of 1730b57cec5SDimitry Andric * tracked values per value site to be \p MaxVals. 1740b57cec5SDimitry Andric */ 1750b57cec5SDimitry Andric void lprofSetMaxValsPerSite(uint32_t MaxVals); 1760b57cec5SDimitry Andric void lprofSetupValueProfiler(); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric /* Return the profile header 'signature' value associated with the current 1790b57cec5SDimitry Andric * executable or shared library. The signature value can be used to for 1800b57cec5SDimitry Andric * a profile name that is unique to this load module so that it does not 1810b57cec5SDimitry Andric * collide with profiles from other binaries. It also allows shared libraries 1820b57cec5SDimitry Andric * to dump merged profile data into its own profile file. */ 1830b57cec5SDimitry Andric uint64_t lprofGetLoadModuleSignature(); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric /* 1860b57cec5SDimitry Andric * Return non zero value if the profile data has already been 1870b57cec5SDimitry Andric * dumped to the file. 1880b57cec5SDimitry Andric */ 1895ffd83dbSDimitry Andric unsigned lprofProfileDumped(void); 1905ffd83dbSDimitry Andric void lprofSetProfileDumped(unsigned); 1915ffd83dbSDimitry Andric 1920b57cec5SDimitry Andric COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *); 1930b57cec5SDimitry Andric COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer; 1940b57cec5SDimitry Andric COMPILER_RT_VISIBILITY extern uint32_t VPBufferSize; 1950b57cec5SDimitry Andric COMPILER_RT_VISIBILITY extern uint32_t VPMaxNumValsPerSite; 1960b57cec5SDimitry Andric /* Pointer to the start of static value counters to be allocted. */ 1970b57cec5SDimitry Andric COMPILER_RT_VISIBILITY extern ValueProfNode *CurrentVNode; 1980b57cec5SDimitry Andric COMPILER_RT_VISIBILITY extern ValueProfNode *EndVNode; 1990b57cec5SDimitry Andric extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *); 2000b57cec5SDimitry Andric 201fe6060f1SDimitry Andric /* 202fe6060f1SDimitry Andric * Write binary ids into profiles if writer is given. 203fe6060f1SDimitry Andric * Return -1 if an error occurs, otherwise, return total size of binary ids. 204fe6060f1SDimitry Andric */ 205fe6060f1SDimitry Andric int __llvm_write_binary_ids(ProfDataWriter *Writer); 206fe6060f1SDimitry Andric 20706c3fb27SDimitry Andric /* 20806c3fb27SDimitry Andric * Write binary id length and then its data, because binary id does not 20906c3fb27SDimitry Andric * have a fixed length. 21006c3fb27SDimitry Andric */ 21106c3fb27SDimitry Andric int lprofWriteOneBinaryId(ProfDataWriter *Writer, uint64_t BinaryIdLen, 21206c3fb27SDimitry Andric const uint8_t *BinaryIdData, 21306c3fb27SDimitry Andric uint64_t BinaryIdPadding); 21406c3fb27SDimitry Andric 2150b57cec5SDimitry Andric #endif 216