xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/profile/InstrProfilingInternal.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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