mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 09:31:03 +03:00
[PGO] Update llvm-profdata-3.9 and profile-rt-39 to LLVM r269788.
This commit is contained in:
parent
e1c06c1e64
commit
103c6f557e
13 changed files with 390 additions and 315 deletions
|
@ -88,6 +88,33 @@ INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \
|
|||
#undef INSTR_PROF_DATA
|
||||
/* INSTR_PROF_DATA end. */
|
||||
|
||||
|
||||
/* 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;
|
||||
* uint64_t Value;
|
||||
* uint64_t Count;
|
||||
* struct ValueProfNode *Next;
|
||||
* } ValueProfNode;
|
||||
*/
|
||||
/* INSTR_PROF_VALUE_NODE start. */
|
||||
#ifndef INSTR_PROF_VALUE_NODE
|
||||
#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer)
|
||||
#else
|
||||
#define INSTR_PROF_DATA_DEFINED
|
||||
#endif
|
||||
INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \
|
||||
ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
|
||||
INSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \
|
||||
ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0))
|
||||
INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
|
||||
ConstantInt::get(llvm::Type::GetInt8PtrTy(Ctx), 0))
|
||||
#undef INSTR_PROF_VALUE_NODE
|
||||
/* INSTR_PROF_VALUE_NODE end. */
|
||||
|
||||
/* INSTR_PROF_RAW_HEADER start */
|
||||
/* Definition of member fields of the raw profile header data structure. */
|
||||
#ifndef INSTR_PROF_RAW_HEADER
|
||||
|
@ -103,8 +130,6 @@ 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 */
|
||||
|
||||
|
@ -133,7 +158,7 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
|
|||
#else
|
||||
#define INSTR_PROF_DATA_DEFINED
|
||||
#endif
|
||||
/* For indirect function call value profiling, the address of the target
|
||||
/* For indirect function call value profiling, the addresses of the target
|
||||
* functions are profiled by the instrumented code. The target addresses are
|
||||
* written in the raw profile data and converted to target function name's MD5
|
||||
* hash by the profile reader during deserialization. Typically, this happens
|
||||
|
@ -363,45 +388,11 @@ typedef struct ValueProfRecordClosure {
|
|||
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);
|
||||
ValueProfRecord *getFirstValueProfRecord(ValueProfData *VPD);
|
||||
ValueProfRecord *getValueProfRecordNext(ValueProfRecord *VPR);
|
||||
InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *VPR);
|
||||
uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites);
|
||||
|
||||
#undef INSTR_PROF_VALUE_PROF_DATA
|
||||
#endif /* INSTR_PROF_VALUE_PROF_DATA */
|
||||
|
@ -495,9 +486,6 @@ 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);
|
||||
|
@ -533,12 +521,15 @@ void serializeValueProfRecordFrom(ValueProfRecord *This,
|
|||
/*!
|
||||
* 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.
|
||||
* memory allocated by the \c Closure's allocator method. If \c
|
||||
* DstData is not null, the caller is expected to set the TotalSize
|
||||
* in DstData.
|
||||
*/
|
||||
ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
||||
ValueProfData *DstData) {
|
||||
uint32_t Kind;
|
||||
uint32_t TotalSize = getValueProfDataSize(Closure);
|
||||
uint32_t TotalSize =
|
||||
DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
|
||||
|
||||
ValueProfData *VPD =
|
||||
DstData ? DstData : Closure->AllocValueProfData(TotalSize);
|
||||
|
@ -556,130 +547,6 @@ ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
|
|||
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] = INSTR_PROF_NULLPTR;
|
||||
continue;
|
||||
}
|
||||
NumValueKinds++;
|
||||
RuntimeRecord->SiteCountArray[I] = (uint8_t *)calloc(N, 1);
|
||||
if (!RuntimeRecord->SiteCountArray[I])
|
||||
return 1;
|
||||
RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
|
||||
for (J = 0; J < N; J++) {
|
||||
/* Compute value count for each site. */
|
||||
uint32_t C = 0;
|
||||
ValueProfNode *Site =
|
||||
Nodes ? RuntimeRecord->NodesKind[I][J] : INSTR_PROF_NULLPTR;
|
||||
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] == INSTR_PROF_NULLPTR)
|
||||
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) {
|
||||
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 = {
|
||||
INSTR_PROF_NULLPTR, getNumValueKindsRT, getNumValueSitesRT,
|
||||
getNumValueDataRT, getNumValueDataForSiteRT, INSTR_PROF_NULLPTR,
|
||||
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 */
|
||||
|
||||
|
@ -711,7 +578,7 @@ serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
|
|||
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129
|
||||
|
||||
/* Raw profile format version (start from 1). */
|
||||
#define INSTR_PROF_RAW_VERSION 3
|
||||
#define INSTR_PROF_RAW_VERSION 4
|
||||
/* Indexed profile format version (start from 1). */
|
||||
#define INSTR_PROF_INDEX_VERSION 4
|
||||
/* Coverage mapping format vresion (start from 0). */
|
||||
|
@ -770,15 +637,6 @@ typedef struct InstrProfValueData {
|
|||
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
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#define INSTR_PROF_VALUE_PROF_DATA
|
||||
#include "InstrProfData.inc"
|
||||
|
||||
char *(*GetEnvHook)(const char *) = 0;
|
||||
COMPILER_RT_VISIBILITY char *(*GetEnvHook)(const char *) = 0;
|
||||
|
||||
COMPILER_RT_WEAK uint64_t __llvm_profile_raw_version = INSTR_PROF_RAW_VERSION;
|
||||
|
||||
|
@ -61,7 +61,7 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
|
|||
ValueProfNode *CurrentVNode = ValueCounters[i];
|
||||
|
||||
while (CurrentVNode) {
|
||||
CurrentVNode->VData.Count = 0;
|
||||
CurrentVNode->Count = 0;
|
||||
CurrentVNode = CurrentVNode->Next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,12 @@ typedef struct __llvm_profile_header {
|
|||
#include "InstrProfData.inc"
|
||||
} __llvm_profile_header;
|
||||
|
||||
typedef struct ValueProfNode * PtrToNodeT;
|
||||
typedef struct ValueProfNode {
|
||||
#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer) Type Name;
|
||||
#include "InstrProfData.inc"
|
||||
} ValueProfNode;
|
||||
|
||||
/*!
|
||||
* \brief Get number of bytes necessary to pad the argument to eight
|
||||
* byte boundary.
|
||||
|
@ -96,14 +102,6 @@ void INSTR_PROF_VALUE_PROF_FUNC(
|
|||
#include "InstrProfData.inc"
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Prepares the value profiling data for output.
|
||||
*
|
||||
* Returns an array of pointers to value profile data.
|
||||
*/
|
||||
struct ValueProfData;
|
||||
struct ValueProfData **__llvm_profile_gather_value_data(uint64_t *Size);
|
||||
|
||||
/*!
|
||||
* \brief Write instrumentation data to the current file.
|
||||
*
|
||||
|
|
|
@ -46,7 +46,7 @@ uint64_t __llvm_profile_get_size_for_buffer_internal(
|
|||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer(char *Buffer) {
|
||||
return lprofWriteData(lprofBufferWriter, Buffer, 0, 0);
|
||||
return lprofWriteData(lprofBufferWriter, Buffer, 0);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
||||
|
@ -54,6 +54,6 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
|
|||
const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
|
||||
const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
|
||||
return lprofWriteDataImpl(lprofBufferWriter, Buffer, DataBegin, DataEnd,
|
||||
CountersBegin, CountersEnd, 0, 0, NamesBegin,
|
||||
CountersBegin, CountersEnd, 0, NamesBegin,
|
||||
NamesEnd);
|
||||
}
|
||||
|
|
|
@ -32,22 +32,25 @@ static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
|||
|
||||
COMPILER_RT_VISIBILITY ProfBufferIO *
|
||||
lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
|
||||
CallocHook = calloc;
|
||||
FreeHook = free;
|
||||
return lprofCreateBufferIO(fileWriter, File, BufferSz);
|
||||
FreeHook = &free;
|
||||
DynamicBufferIOBuffer = (uint8_t *)calloc(BufferSz, 1);
|
||||
VPBufferSize = BufferSz;
|
||||
return lprofCreateBufferIO(fileWriter, File);
|
||||
}
|
||||
|
||||
static void setupIOBuffer() {
|
||||
const char *BufferSzStr = 0;
|
||||
BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
|
||||
if (BufferSzStr && BufferSzStr[0]) {
|
||||
VPBufferSize = atoi(BufferSzStr);
|
||||
DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int writeFile(FILE *File) {
|
||||
const char *BufferSzStr = 0;
|
||||
uint64_t ValueDataSize = 0;
|
||||
struct ValueProfData **ValueDataArray =
|
||||
__llvm_profile_gather_value_data(&ValueDataSize);
|
||||
FreeHook = &free;
|
||||
CallocHook = &calloc;
|
||||
BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
|
||||
if (BufferSzStr && BufferSzStr[0])
|
||||
VPBufferSize = atoi(BufferSzStr);
|
||||
return lprofWriteData(fileWriter, File, ValueDataArray, ValueDataSize);
|
||||
setupIOBuffer();
|
||||
return lprofWriteData(fileWriter, File, lprofGetVPDataReader());
|
||||
}
|
||||
|
||||
static int writeFileWithName(const char *OutputName) {
|
||||
|
|
|
@ -68,12 +68,13 @@ typedef struct ProfBufferIO {
|
|||
} ProfBufferIO;
|
||||
|
||||
/* The creator interface used by testing. */
|
||||
ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t DefaultBufferSz);
|
||||
ProfBufferIO *lprofCreateBufferIOInternal(void *File, uint32_t BufferSz);
|
||||
|
||||
/*!
|
||||
* This is the interface to create a handle for buffered IO.
|
||||
*/
|
||||
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File,
|
||||
uint32_t DefaultBufferSz);
|
||||
ProfBufferIO *lprofCreateBufferIO(WriterCallback FileWriter, void *File);
|
||||
|
||||
/*!
|
||||
* The interface to destroy the bufferIO handle and reclaim
|
||||
* the memory.
|
||||
|
@ -98,26 +99,61 @@ int lprofBufferIOFlush(ProfBufferIO *BufferIO);
|
|||
uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
|
||||
void **WriterCtx);
|
||||
|
||||
struct ValueProfData;
|
||||
struct ValueProfRecord;
|
||||
struct InstrProfValueData;
|
||||
struct ValueProfNode;
|
||||
|
||||
/*!
|
||||
* The class that defines a set of methods to read value profile
|
||||
* data for streaming/serialization from the instrumentation runtime.
|
||||
*/
|
||||
typedef struct VPDataReaderType {
|
||||
uint32_t (*InitRTRecord)(const __llvm_profile_data *Data,
|
||||
uint8_t *SiteCountArray[]);
|
||||
/* Function pointer to getValueProfRecordHeader method. */
|
||||
uint32_t (*GetValueProfRecordHeaderSize)(uint32_t NumSites);
|
||||
/* Function pointer to getFristValueProfRecord method. */
|
||||
struct ValueProfRecord *(*GetFirstValueProfRecord)(struct ValueProfData *);
|
||||
/* Return the number of value data for site \p Site. */
|
||||
uint32_t (*GetNumValueDataForSite)(uint32_t VK, uint32_t Site);
|
||||
/* Return the total size of the value profile data of the
|
||||
* current function. */
|
||||
uint32_t (*GetValueProfDataSize)(void);
|
||||
/*!
|
||||
* Read the next \p N value data for site \p Site and store the data
|
||||
* in \p Dst. \p StartNode is the first value node to start with if
|
||||
* it is not null. The function returns the pointer to the value
|
||||
* node pointer to be used as the \p StartNode of the next batch reading.
|
||||
* If there is nothing left, it returns NULL.
|
||||
*/
|
||||
struct ValueProfNode *(*GetValueData)(uint32_t ValueKind, uint32_t Site,
|
||||
struct InstrProfValueData *Dst,
|
||||
struct ValueProfNode *StartNode,
|
||||
uint32_t N);
|
||||
} VPDataReaderType;
|
||||
|
||||
int lprofWriteData(WriterCallback Writer, void *WriterCtx,
|
||||
struct ValueProfData **ValueDataArray,
|
||||
const uint64_t ValueDataSize);
|
||||
VPDataReaderType *VPDataReader);
|
||||
int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const uint64_t *CountersBegin,
|
||||
const uint64_t *CountersEnd,
|
||||
struct ValueProfData **ValueDataBeginArray,
|
||||
const uint64_t ValueDataSize, const char *NamesBegin,
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd);
|
||||
|
||||
/* Merge value profile data pointed to by SrcValueProfData into
|
||||
* in-memory profile counters pointed by to DstData. */
|
||||
void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData,
|
||||
__llvm_profile_data *DstData);
|
||||
|
||||
extern char *(*GetEnvHook)(const char *);
|
||||
extern void (*FreeHook)(void *);
|
||||
extern void *(*CallocHook)(size_t, size_t);
|
||||
VPDataReaderType *lprofGetVPDataReader();
|
||||
|
||||
COMPILER_RT_VISIBILITY extern char *(*GetEnvHook)(const char *);
|
||||
COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *);
|
||||
COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer;
|
||||
COMPILER_RT_VISIBILITY extern uint32_t VPBufferSize;
|
||||
extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *);
|
||||
extern uint32_t VPBufferSize;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,8 +46,7 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
|
|||
|
||||
if (ProfileSize < sizeof(__llvm_profile_header) +
|
||||
Header->DataSize * sizeof(__llvm_profile_data) +
|
||||
Header->NamesSize + Header->CountersSize +
|
||||
Header->ValueDataSize)
|
||||
Header->NamesSize + Header->CountersSize)
|
||||
return 1;
|
||||
|
||||
for (SrcData = SrcDataStart,
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
#define COMPILER_RT_ALIGNAS(x) __declspec(align(x))
|
||||
#define COMPILER_RT_VISIBILITY
|
||||
#define COMPILER_RT_WEAK __declspec(selectany)
|
||||
#define COMPILER_RT_ALLOCA _alloca
|
||||
#elif __GNUC__
|
||||
#define COMPILER_RT_ALIGNAS(x) __attribute__((aligned(x)))
|
||||
#define COMPILER_RT_VISIBILITY __attribute__((visibility("hidden")))
|
||||
#define COMPILER_RT_WEAK __attribute__((weak))
|
||||
#define COMPILER_RT_ALLOCA __builtin_alloca
|
||||
#endif
|
||||
|
||||
#define COMPILER_RT_SECTION(Sect) __attribute__((section(Sect)))
|
||||
|
@ -25,7 +27,7 @@
|
|||
#define COMPILER_RT_MAX_HOSTLEN 128
|
||||
#ifdef _MSC_VER
|
||||
#define COMPILER_RT_GETHOSTNAME(Name, Len) gethostname(Name, Len)
|
||||
#elif defined(__PS4__)
|
||||
#elif defined(__ORBIS__)
|
||||
#define COMPILER_RT_GETHOSTNAME(Name, Len) (-1)
|
||||
#else
|
||||
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
|
||||
|
@ -42,19 +44,29 @@
|
|||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||
(InterlockedCompareExchange64((LONGLONG volatile *)Ptr, (LONGLONG)NewV, \
|
||||
(LONGLONG)OldV) == (LONGLONG)OldV)
|
||||
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||
(DomType *)InterlockedExchangeAdd64((LONGLONG volatile *)&PtrVar, \
|
||||
(LONGLONG)sizeof(DomType) * PtrIncr)
|
||||
#else /* !defined(_WIN64) */
|
||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||
(InterlockedCompareExchange((LONG volatile *)Ptr, (LONG)NewV, (LONG)OldV) == \
|
||||
(LONG)OldV)
|
||||
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||
(DomType *)InterlockedExchangeAdd((LONG volatile *)&PtrVar, \
|
||||
(LONG)sizeof(DomType) * PtrIncr)
|
||||
#endif
|
||||
#else /* !defined(_MSC_VER) */
|
||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||
__sync_bool_compare_and_swap(Ptr, OldV, NewV)
|
||||
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||
(DomType *)__sync_fetch_and_add((long *)&PtrVar, sizeof(DomType) * PtrIncr)
|
||||
#endif
|
||||
#else /* COMPILER_RT_HAS_ATOMICS != 1 */
|
||||
#include "InstrProfilingUtil.h"
|
||||
#define COMPILER_RT_BOOL_CMPXCHG(Ptr, OldV, NewV) \
|
||||
lprofBoolCmpXchg((void **)Ptr, OldV, NewV)
|
||||
#define COMPILER_RT_PTR_FETCH_ADD(DomType, PtrVar, PtrIncr) \
|
||||
(DomType *)lprofPtrFetchAdd((void **)&PtrVar, sizeof(DomType) * PtrIncr)
|
||||
#endif
|
||||
|
||||
#define PROF_ERR(Format, ...) \
|
||||
|
|
|
@ -51,6 +51,13 @@ uint32_t lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
COMPILER_RT_VISIBILITY
|
||||
void *lprofPtrFetchAdd(void **Mem, long ByteIncr) {
|
||||
void *Old = *Mem;
|
||||
*((char **)Mem) += ByteIncr;
|
||||
return Old;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER_RT_HAS_UNAME
|
||||
|
|
|
@ -16,12 +16,13 @@
|
|||
void __llvm_profile_recursive_mkdir(char *Pathname);
|
||||
|
||||
/* PS4 doesn't have getenv. Define a shim. */
|
||||
#if __PS4__
|
||||
#if __ORBIS__
|
||||
static inline char *getenv(const char *name) { return NULL; }
|
||||
#endif /* #if __PS4__ */
|
||||
#endif /* #if __ORBIS__ */
|
||||
|
||||
int lprofGetHostName(char *Name, int Len);
|
||||
|
||||
unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
|
||||
void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
|
||||
|
||||
#endif /* PROFILE_INSTRPROFILINGUTIL_H */
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#define PROF_OOM_RETURN(Msg) \
|
||||
{ \
|
||||
PROF_OOM(Msg) \
|
||||
free(ValueDataArray); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
|
@ -86,8 +85,8 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
|||
|
||||
uint8_t VDataCount = 0;
|
||||
while (CurrentVNode) {
|
||||
if (TargetValue == CurrentVNode->VData.Value) {
|
||||
CurrentVNode->VData.Count++;
|
||||
if (TargetValue == CurrentVNode->Value) {
|
||||
CurrentVNode->Count++;
|
||||
return;
|
||||
}
|
||||
PrevVNode = CurrentVNode;
|
||||
|
@ -102,8 +101,8 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
|||
if (!CurrentVNode)
|
||||
return;
|
||||
|
||||
CurrentVNode->VData.Value = TargetValue;
|
||||
CurrentVNode->VData.Count++;
|
||||
CurrentVNode->Value = TargetValue;
|
||||
CurrentVNode->Count++;
|
||||
|
||||
uint32_t Success = 0;
|
||||
if (!ValueCounters[CounterIndex])
|
||||
|
@ -118,51 +117,109 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data,
|
|||
}
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY ValueProfData **
|
||||
__llvm_profile_gather_value_data(uint64_t *ValueDataSize) {
|
||||
size_t S = 0;
|
||||
__llvm_profile_data *I;
|
||||
ValueProfData **ValueDataArray;
|
||||
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
|
||||
if (!ValueDataSize)
|
||||
return NULL;
|
||||
|
||||
ValueDataArray = (ValueProfData **)calloc(
|
||||
__llvm_profile_get_data_size(DataBegin, DataEnd), sizeof(void *));
|
||||
if (!ValueDataArray)
|
||||
PROF_OOM_RETURN("Failed to write value profile data ");
|
||||
|
||||
/*
|
||||
* Compute the total Size of the buffer to hold ValueProfData
|
||||
* structures for functions with value profile data.
|
||||
* 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.
|
||||
*/
|
||||
for (I = (__llvm_profile_data *)DataBegin; I < DataEnd; ++I) {
|
||||
ValueProfRuntimeRecord R;
|
||||
if (initializeValueProfRuntimeRecord(&R, I->NumValueSites, I->Values))
|
||||
PROF_OOM_RETURN("Failed to write value profile data ");
|
||||
typedef struct ValueProfRuntimeRecord {
|
||||
const __llvm_profile_data *Data;
|
||||
ValueProfNode **NodesKind[IPVK_Last + 1];
|
||||
uint8_t **SiteCountArray;
|
||||
} ValueProfRuntimeRecord;
|
||||
|
||||
/* Compute the size of ValueProfData from this runtime record. */
|
||||
if (getNumValueKindsRT(&R) != 0) {
|
||||
ValueProfData *VD = NULL;
|
||||
uint32_t VS = getValueProfDataSizeRT(&R);
|
||||
VD = (ValueProfData *)calloc(VS, sizeof(uint8_t));
|
||||
if (!VD)
|
||||
PROF_OOM_RETURN("Failed to write value profile data ");
|
||||
serializeValueProfDataFromRT(&R, VD);
|
||||
ValueDataArray[I - DataBegin] = VD;
|
||||
S += VS;
|
||||
}
|
||||
finalizeValueProfRuntimeRecord(&R);
|
||||
/* ValueProfRecordClosure Interface implementation. */
|
||||
|
||||
static uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
|
||||
return ((const ValueProfRuntimeRecord *)R)->Data->NumValueSites[VK];
|
||||
}
|
||||
|
||||
if (!S) {
|
||||
free(ValueDataArray);
|
||||
ValueDataArray = NULL;
|
||||
static uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
|
||||
uint32_t S = 0, I;
|
||||
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
||||
if (Record->SiteCountArray[VK] == INSTR_PROF_NULLPTR)
|
||||
return 0;
|
||||
for (I = 0; I < Record->Data->NumValueSites[VK]; I++)
|
||||
S += Record->SiteCountArray[VK][I];
|
||||
return S;
|
||||
}
|
||||
|
||||
*ValueDataSize = S;
|
||||
return ValueDataArray;
|
||||
static uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK,
|
||||
uint32_t S) {
|
||||
const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
|
||||
return Record->SiteCountArray[VK][S];
|
||||
}
|
||||
|
||||
static ValueProfRuntimeRecord RTRecord;
|
||||
static ValueProfRecordClosure RTRecordClosure = {
|
||||
&RTRecord, INSTR_PROF_NULLPTR, /* GetNumValueKinds */
|
||||
getNumValueSitesRT, getNumValueDataRT, getNumValueDataForSiteRT,
|
||||
INSTR_PROF_NULLPTR, /* RemapValueData */
|
||||
INSTR_PROF_NULLPTR, /* GetValueForSite, */
|
||||
INSTR_PROF_NULLPTR /* AllocValueProfData */
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
initializeValueProfRuntimeRecord(const __llvm_profile_data *Data,
|
||||
uint8_t *SiteCountArray[]) {
|
||||
unsigned I, J, S = 0, NumValueKinds = 0;
|
||||
ValueProfNode **Nodes = (ValueProfNode **)Data->Values;
|
||||
RTRecord.Data = Data;
|
||||
RTRecord.SiteCountArray = SiteCountArray;
|
||||
for (I = 0; I <= IPVK_Last; I++) {
|
||||
uint16_t N = Data->NumValueSites[I];
|
||||
if (!N)
|
||||
continue;
|
||||
|
||||
NumValueKinds++;
|
||||
|
||||
RTRecord.NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
|
||||
for (J = 0; J < N; J++) {
|
||||
/* Compute value count for each site. */
|
||||
uint32_t C = 0;
|
||||
ValueProfNode *Site =
|
||||
Nodes ? RTRecord.NodesKind[I][J] : INSTR_PROF_NULLPTR;
|
||||
while (Site) {
|
||||
C++;
|
||||
Site = Site->Next;
|
||||
}
|
||||
if (C > UCHAR_MAX)
|
||||
C = UCHAR_MAX;
|
||||
RTRecord.SiteCountArray[I][J] = C;
|
||||
}
|
||||
S += N;
|
||||
}
|
||||
return NumValueKinds;
|
||||
}
|
||||
|
||||
static ValueProfNode *getNextNValueData(uint32_t VK, uint32_t Site,
|
||||
InstrProfValueData *Dst,
|
||||
ValueProfNode *StartNode, uint32_t N) {
|
||||
unsigned I;
|
||||
ValueProfNode *VNode = StartNode ? StartNode : RTRecord.NodesKind[VK][Site];
|
||||
for (I = 0; I < N; I++) {
|
||||
Dst[I].Value = VNode->Value;
|
||||
Dst[I].Count = VNode->Count;
|
||||
VNode = VNode->Next;
|
||||
}
|
||||
return VNode;
|
||||
}
|
||||
|
||||
static uint32_t getValueProfDataSizeWrapper() {
|
||||
return getValueProfDataSize(&RTRecordClosure);
|
||||
}
|
||||
|
||||
static uint32_t getNumValueDataForSiteWrapper(uint32_t VK, uint32_t S) {
|
||||
return getNumValueDataForSiteRT(&RTRecord, VK, S);
|
||||
}
|
||||
|
||||
static VPDataReaderType TheVPDataReader = {
|
||||
initializeValueProfRuntimeRecord, getValueProfRecordHeaderSize,
|
||||
getFirstValueProfRecord, getNumValueDataForSiteWrapper,
|
||||
getValueProfDataSizeWrapper, getNextNValueData};
|
||||
|
||||
COMPILER_RT_VISIBILITY VPDataReaderType *lprofGetVPDataReader() {
|
||||
return &TheVPDataReader;
|
||||
}
|
||||
|
|
|
@ -9,13 +9,24 @@
|
|||
|
||||
#include "InstrProfiling.h"
|
||||
#include "InstrProfilingInternal.h"
|
||||
#ifdef _MSC_VER
|
||||
/* For _alloca */
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#define INSTR_PROF_VALUE_PROF_DATA
|
||||
#include "InstrProfData.inc"
|
||||
void (*FreeHook)(void *) = NULL;
|
||||
void* (*CallocHook)(size_t, size_t) = NULL;
|
||||
uint32_t VPBufferSize = 0;
|
||||
|
||||
COMPILER_RT_VISIBILITY void (*FreeHook)(void *) = NULL;
|
||||
static ProfBufferIO TheBufferIO;
|
||||
#define VP_BUFFER_SIZE 8 * 1024
|
||||
static uint8_t BufferIOBuffer[VP_BUFFER_SIZE];
|
||||
static InstrProfValueData VPDataArray[16];
|
||||
static uint32_t VPDataArraySize = sizeof(VPDataArray) / sizeof(*VPDataArray);
|
||||
|
||||
COMPILER_RT_VISIBILITY uint8_t *DynamicBufferIOBuffer = 0;
|
||||
COMPILER_RT_VISIBILITY uint32_t VPBufferSize = 0;
|
||||
|
||||
/* The buffer writer is reponsponsible in keeping writer state
|
||||
* across the call.
|
||||
|
@ -43,20 +54,23 @@ static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter,
|
|||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY ProfBufferIO *
|
||||
lprofCreateBufferIO(WriterCallback FileWriter, void *File, uint32_t BufferSz) {
|
||||
ProfBufferIO *BufferIO = (ProfBufferIO *)CallocHook(1, sizeof(ProfBufferIO));
|
||||
uint8_t *Buffer = (uint8_t *)CallocHook(1, BufferSz);
|
||||
lprofCreateBufferIO(WriterCallback FileWriter, void *File) {
|
||||
uint8_t *Buffer = DynamicBufferIOBuffer;
|
||||
uint32_t BufferSize = VPBufferSize;
|
||||
if (!Buffer) {
|
||||
FreeHook(BufferIO);
|
||||
return 0;
|
||||
Buffer = &BufferIOBuffer[0];
|
||||
BufferSize = sizeof(BufferIOBuffer);
|
||||
}
|
||||
llvmInitBufferIO(BufferIO, FileWriter, File, Buffer, BufferSz);
|
||||
return BufferIO;
|
||||
llvmInitBufferIO(&TheBufferIO, FileWriter, File, Buffer, BufferSize);
|
||||
return &TheBufferIO;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) {
|
||||
FreeHook(BufferIO->BufferStart);
|
||||
FreeHook(BufferIO);
|
||||
if (DynamicBufferIOBuffer) {
|
||||
FreeHook(DynamicBufferIOBuffer);
|
||||
DynamicBufferIOBuffer = 0;
|
||||
VPBufferSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int
|
||||
|
@ -91,41 +105,116 @@ COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
|
||||
void *WriterCtx,
|
||||
ValueProfData **ValueDataArray,
|
||||
const uint64_t ValueDataSize) {
|
||||
/* Match logic in __llvm_profile_write_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
|
||||
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *NamesBegin = __llvm_profile_begin_names();
|
||||
const char *NamesEnd = __llvm_profile_end_names();
|
||||
return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
|
||||
CountersBegin, CountersEnd, ValueDataArray,
|
||||
ValueDataSize, NamesBegin, NamesEnd);
|
||||
/* Write out value profile data for function specified with \c Data.
|
||||
* The implementation does not use the method \c serializeValueProfData
|
||||
* which depends on dynamic memory allocation. In this implementation,
|
||||
* value profile data is written out to \c BufferIO piecemeal.
|
||||
*/
|
||||
static int writeOneValueProfData(ProfBufferIO *BufferIO,
|
||||
VPDataReaderType *VPDataReader,
|
||||
const __llvm_profile_data *Data) {
|
||||
unsigned I, NumValueKinds = 0;
|
||||
ValueProfData VPHeader;
|
||||
uint8_t *SiteCountArray[IPVK_Last + 1];
|
||||
|
||||
for (I = 0; I <= IPVK_Last; I++) {
|
||||
if (!Data->NumValueSites[I])
|
||||
SiteCountArray[I] = 0;
|
||||
else {
|
||||
uint32_t Sz =
|
||||
VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
|
||||
offsetof(ValueProfRecord, SiteCountArray);
|
||||
/* Only use alloca for this small byte array to avoid excessive
|
||||
* stack growth. */
|
||||
SiteCountArray[I] = (uint8_t *)COMPILER_RT_ALLOCA(Sz);
|
||||
memset(SiteCountArray[I], 0, Sz);
|
||||
}
|
||||
}
|
||||
|
||||
#define VP_BUFFER_SIZE 8 * 1024
|
||||
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
||||
ValueProfData **ValueDataBegin,
|
||||
uint64_t NumVData) {
|
||||
ProfBufferIO *BufferIO;
|
||||
uint32_t I = 0, BufferSz;
|
||||
|
||||
if (!ValueDataBegin)
|
||||
/* If NumValueKinds returned is 0, there is nothing to write, report
|
||||
success and return. This should match the raw profile reader's behavior. */
|
||||
if (!(NumValueKinds = VPDataReader->InitRTRecord(Data, SiteCountArray)))
|
||||
return 0;
|
||||
|
||||
BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE;
|
||||
BufferIO = lprofCreateBufferIO(Writer, WriterCtx, BufferSz);
|
||||
/* First write the header structure. */
|
||||
VPHeader.TotalSize = VPDataReader->GetValueProfDataSize();
|
||||
VPHeader.NumValueKinds = NumValueKinds;
|
||||
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPHeader,
|
||||
sizeof(ValueProfData)))
|
||||
return -1;
|
||||
|
||||
for (I = 0; I < NumVData; I++) {
|
||||
ValueProfData *CurVData = ValueDataBegin[I];
|
||||
if (!CurVData)
|
||||
/* Make sure nothing else needs to be written before value profile
|
||||
* records. */
|
||||
if ((void *)VPDataReader->GetFirstValueProfRecord(&VPHeader) !=
|
||||
(void *)(&VPHeader + 1))
|
||||
return -1;
|
||||
|
||||
/* Write out the value profile record for each value kind
|
||||
* one by one. */
|
||||
for (I = 0; I <= IPVK_Last; I++) {
|
||||
uint32_t J;
|
||||
ValueProfRecord RecordHeader;
|
||||
/* The size of the value prof record header without counting the
|
||||
* site count array .*/
|
||||
uint32_t RecordHeaderSize = offsetof(ValueProfRecord, SiteCountArray);
|
||||
uint32_t SiteCountArraySize;
|
||||
|
||||
if (!Data->NumValueSites[I])
|
||||
continue;
|
||||
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)CurVData,
|
||||
CurVData->TotalSize) != 0)
|
||||
|
||||
/* Write out the record header. */
|
||||
RecordHeader.Kind = I;
|
||||
RecordHeader.NumValueSites = Data->NumValueSites[I];
|
||||
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&RecordHeader,
|
||||
RecordHeaderSize))
|
||||
return -1;
|
||||
|
||||
/* Write out the site value count array including padding space. */
|
||||
SiteCountArraySize =
|
||||
VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
|
||||
RecordHeaderSize;
|
||||
if (lprofBufferIOWrite(BufferIO, SiteCountArray[I], SiteCountArraySize))
|
||||
return -1;
|
||||
|
||||
/* Write out the value profile data for each value site. */
|
||||
for (J = 0; J < Data->NumValueSites[I]; J++) {
|
||||
uint32_t NRead, NRemain;
|
||||
ValueProfNode *NextStartNode = 0;
|
||||
NRemain = VPDataReader->GetNumValueDataForSite(I, J);
|
||||
if (!NRemain)
|
||||
continue;
|
||||
/* Read and write out value data in small chunks till it is done. */
|
||||
do {
|
||||
NRead = (NRemain > VPDataArraySize ? VPDataArraySize : NRemain);
|
||||
NextStartNode =
|
||||
VPDataReader->GetValueData(I, /* ValueKind */
|
||||
J, /* Site */
|
||||
&VPDataArray[0], NextStartNode, NRead);
|
||||
if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPDataArray[0],
|
||||
NRead * sizeof(InstrProfValueData)))
|
||||
return -1;
|
||||
NRemain -= NRead;
|
||||
} while (NRemain != 0);
|
||||
}
|
||||
}
|
||||
/* All done report success. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
||||
VPDataReaderType *VPDataReader,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd) {
|
||||
ProfBufferIO *BufferIO;
|
||||
const __llvm_profile_data *DI = 0;
|
||||
|
||||
if (!VPDataReader)
|
||||
return 0;
|
||||
|
||||
BufferIO = lprofCreateBufferIO(Writer, WriterCtx);
|
||||
|
||||
for (DI = DataBegin; DI < DataEnd; DI++) {
|
||||
if (writeOneValueProfData(BufferIO, VPDataReader, DI))
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -136,13 +225,28 @@ static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
|
||||
void *WriterCtx,
|
||||
VPDataReaderType *VPDataReader) {
|
||||
/* Match logic in __llvm_profile_write_buffer(). */
|
||||
const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
|
||||
const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
|
||||
const uint64_t *CountersBegin = __llvm_profile_begin_counters();
|
||||
const uint64_t *CountersEnd = __llvm_profile_end_counters();
|
||||
const char *NamesBegin = __llvm_profile_begin_names();
|
||||
const char *NamesEnd = __llvm_profile_end_names();
|
||||
return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
|
||||
CountersBegin, CountersEnd, VPDataReader,
|
||||
NamesBegin, NamesEnd);
|
||||
}
|
||||
|
||||
COMPILER_RT_VISIBILITY int
|
||||
lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
||||
const __llvm_profile_data *DataBegin,
|
||||
const __llvm_profile_data *DataEnd,
|
||||
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
|
||||
ValueProfData **ValueDataBegin, const uint64_t ValueDataSize,
|
||||
const char *NamesBegin, const char *NamesEnd) {
|
||||
VPDataReaderType *VPDataReader, const char *NamesBegin,
|
||||
const char *NamesEnd) {
|
||||
|
||||
/* Calculate size of sections. */
|
||||
const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
|
||||
|
@ -159,7 +263,7 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
|||
if (!DataSize)
|
||||
return 0;
|
||||
|
||||
/* Initialize header struture. */
|
||||
/* Initialize header structure. */
|
||||
#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init;
|
||||
#include "InstrProfData.inc"
|
||||
|
||||
|
@ -172,5 +276,6 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
|
|||
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
|
||||
return -1;
|
||||
|
||||
return writeValueProfData(Writer, WriterCtx, ValueDataBegin, DataSize);
|
||||
return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
|
||||
DataEnd);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue