blob: 6153a00509a3edb89acbb8ec7bd3984d8b7849fe [file] [log] [blame]
Xinliang David Li1d8d46a2015-11-18 21:08:03 +00001/*===- InstrProfilingWriter.c - Write instrumentation to a file or buffer -===*\
2|*
3|* The LLVM Compiler Infrastructure
4|*
5|* This file is distributed under the University of Illinois Open Source
6|* License. See LICENSE.TXT for details.
7|*
8\*===----------------------------------------------------------------------===*/
9
10#include "InstrProfiling.h"
11#include "InstrProfilingInternal.h"
Xinliang David Libaf55d82015-12-22 18:57:15 +000012#include <string.h>
13
Xinliang David Li54dd6832015-12-29 07:13:59 +000014#define INSTR_PROF_VALUE_PROF_DATA
15#include "InstrProfData.inc"
16void (*FreeHook)(void *) = NULL;
17void* (*CallocHook)(size_t, size_t) = NULL;
18uint32_t VPBufferSize = 0;
19
Xinliang David Libaf55d82015-12-22 18:57:15 +000020/* The buffer writer is reponsponsible in keeping writer state
21 * across the call.
22 */
23COMPILER_RT_VISIBILITY uint32_t llvmBufferWriter(ProfDataIOVec *IOVecs,
24 uint32_t NumIOVecs,
25 void **WriterCtx) {
26 uint32_t I;
27 char **Buffer = (char **)WriterCtx;
28 for (I = 0; I < NumIOVecs; I++) {
29 size_t Length = IOVecs[I].ElmSize * IOVecs[I].NumElm;
30 memcpy(*Buffer, IOVecs[I].Data, Length);
31 *Buffer += Length;
32 }
33 return 0;
34}
Xinliang David Li1d8d46a2015-11-18 21:08:03 +000035
Xinliang David Liabfd5532015-12-16 03:29:15 +000036COMPILER_RT_VISIBILITY int llvmWriteProfData(WriterCallback Writer,
37 void *WriterCtx,
Xinliang David Li54dd6832015-12-29 07:13:59 +000038 ValueProfData **ValueDataArray,
Xinliang David Liabfd5532015-12-16 03:29:15 +000039 const uint64_t ValueDataSize) {
Xinliang David Li1d8d46a2015-11-18 21:08:03 +000040 /* Match logic in __llvm_profile_write_buffer(). */
41 const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
42 const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
43 const uint64_t *CountersBegin = __llvm_profile_begin_counters();
44 const uint64_t *CountersEnd = __llvm_profile_end_counters();
45 const char *NamesBegin = __llvm_profile_begin_names();
46 const char *NamesEnd = __llvm_profile_end_names();
Xinliang David Li2d5bf072015-11-21 04:16:42 +000047 return llvmWriteProfDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
Xinliang David Li54dd6832015-12-29 07:13:59 +000048 CountersBegin, CountersEnd, ValueDataArray,
Xinliang David Li6e557162015-11-18 21:11:46 +000049 ValueDataSize, NamesBegin, NamesEnd);
Xinliang David Li1d8d46a2015-11-18 21:08:03 +000050}
51
Xinliang David Li54dd6832015-12-29 07:13:59 +000052#define VP_BUFFER_SIZE 8 * 1024
53static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
54 ValueProfData **ValueDataBegin,
55 uint64_t NumVData) {
56 ValueProfData **ValueDataArray = ValueDataBegin;
57 char *BufferStart = 0, *Buffer;
58 ValueProfData *CurVData;
59 uint32_t I = 0, BufferSz;
60
61 if (!ValueDataBegin)
62 return 0;
63
64 BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE;
65 BufferStart = (char *)CallocHook(BufferSz, sizeof(uint8_t));
66 if (!BufferStart)
67 return -1;
68
69 uint32_t WriteSize = 0;
70 Buffer = BufferStart;
71 do {
72 CurVData = ValueDataArray[I];
73 if (!CurVData) {
74 I++;
75 continue;
76 }
77
78 /* Buffer is full or not large enough, it is time to flush. */
79 if (CurVData->TotalSize + WriteSize > BufferSz) {
80 if (WriteSize) {
81 ProfDataIOVec IO[] = {{BufferStart, sizeof(uint8_t), WriteSize}};
82 if (Writer(IO, 1, &WriterCtx))
83 return -1;
84 WriteSize = 0;
85 Buffer = BufferStart;
86 }
87 /* Special case, bypass the buffer completely. */
88 if (CurVData->TotalSize > BufferSz) {
89 ProfDataIOVec IO[] = {{CurVData, sizeof(uint8_t), CurVData->TotalSize}};
90 if (Writer(IO, 1, &WriterCtx))
91 return -1;
92 FreeHook(ValueDataArray[I]);
93 I++;
94 }
95 } else {
96 /* Write the data to buffer */
97 ProfDataIOVec IO[] = {{CurVData, sizeof(uint8_t), CurVData->TotalSize}};
98 llvmBufferWriter(IO, 1, (void **)&Buffer);
99 WriteSize += CurVData->TotalSize;
100 FreeHook(ValueDataArray[I]);
101 I++;
102 }
103 } while (I < NumVData);
104
105 /* Final flush. */
106 if (WriteSize) {
107 ProfDataIOVec IO[] = {{BufferStart, sizeof(uint8_t), WriteSize}};
108 if (Writer(IO, 1, &WriterCtx))
109 return -1;
110 }
111
112 FreeHook(ValueDataBegin);
113 FreeHook(BufferStart);
114 return 0;
115}
116
Xinliang David Liabfd5532015-12-16 03:29:15 +0000117COMPILER_RT_VISIBILITY int llvmWriteProfDataImpl(
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000118 WriterCallback Writer, void *WriterCtx,
Xinliang David Li1d8d46a2015-11-18 21:08:03 +0000119 const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
120 const uint64_t *CountersBegin, const uint64_t *CountersEnd,
Xinliang David Li54dd6832015-12-29 07:13:59 +0000121 ValueProfData **ValueDataBegin, const uint64_t ValueDataSize,
Xinliang David Li1d8d46a2015-11-18 21:08:03 +0000122 const char *NamesBegin, const char *NamesEnd) {
123
124 /* Calculate size of sections. */
125 const uint64_t DataSize = DataEnd - DataBegin;
126 const uint64_t CountersSize = CountersEnd - CountersBegin;
127 const uint64_t NamesSize = NamesEnd - NamesBegin;
128 const uint64_t Padding = __llvm_profile_get_num_padding_bytes(NamesSize);
129
130 /* Enough zeroes for padding. */
131 const char Zeroes[sizeof(uint64_t)] = {0};
132
133 /* Create the header. */
134 __llvm_profile_header Header;
135
136 if (!DataSize)
137 return 0;
138
Xinliang David Li6376db52015-11-23 18:36:40 +0000139 /* Initialize header struture. */
140#define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init;
141#include "InstrProfData.inc"
Xinliang David Li1d8d46a2015-11-18 21:08:03 +0000142
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000143 /* Write the data. */
Xinliang David Li54dd6832015-12-29 07:13:59 +0000144 ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1},
145 {DataBegin, sizeof(__llvm_profile_data), DataSize},
146 {CountersBegin, sizeof(uint64_t), CountersSize},
147 {NamesBegin, sizeof(uint8_t), NamesSize},
148 {Zeroes, sizeof(uint8_t), Padding}};
Joerg Sonnenbergerd6487b22015-12-04 00:40:07 +0000149 if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
Xinliang David Li2d5bf072015-11-21 04:16:42 +0000150 return -1;
Xinliang David Li54dd6832015-12-29 07:13:59 +0000151
152 return writeValueProfData(Writer, WriterCtx, ValueDataBegin, DataSize);
Xinliang David Li1d8d46a2015-11-18 21:08:03 +0000153}