1/*===- InstrProfilingBuffer.c - Write instrumentation to a memory 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 <string.h>
12
13__attribute__((visibility("hidden")))
14uint64_t __llvm_profile_get_size_for_buffer(void) {
15  /* Match logic in __llvm_profile_write_buffer(). */
16  const uint64_t NamesSize = PROFILE_RANGE_SIZE(names) * sizeof(char);
17  const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
18  return sizeof(uint64_t) * PROFILE_HEADER_SIZE +
19     PROFILE_RANGE_SIZE(data) * sizeof(__llvm_profile_data) +
20     PROFILE_RANGE_SIZE(counters) * sizeof(uint64_t) +
21     NamesSize + Padding;
22}
23
24__attribute__((visibility("hidden")))
25int __llvm_profile_write_buffer(char *Buffer) {
26  /* Match logic in __llvm_profile_get_size_for_buffer().
27   * Match logic in __llvm_profile_write_file().
28   */
29  const __llvm_profile_data *DataBegin = __llvm_profile_data_begin();
30  const __llvm_profile_data *DataEnd = __llvm_profile_data_end();
31  const uint64_t *CountersBegin = __llvm_profile_counters_begin();
32  const uint64_t *CountersEnd   = __llvm_profile_counters_end();
33  const char *NamesBegin = __llvm_profile_names_begin();
34  const char *NamesEnd   = __llvm_profile_names_end();
35
36  /* Calculate size of sections. */
37  const uint64_t DataSize = DataEnd - DataBegin;
38  const uint64_t CountersSize = CountersEnd - CountersBegin;
39  const uint64_t NamesSize = NamesEnd - NamesBegin;
40  const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
41
42  /* Enough zeroes for padding. */
43  const char Zeroes[sizeof(uint64_t)] = {0};
44
45  /* Create the header. */
46  uint64_t Header[PROFILE_HEADER_SIZE];
47  Header[0] = __llvm_profile_get_magic();
48  Header[1] = __llvm_profile_get_version();
49  Header[2] = DataSize;
50  Header[3] = CountersSize;
51  Header[4] = NamesSize;
52  Header[5] = (uintptr_t)CountersBegin;
53  Header[6] = (uintptr_t)NamesBegin;
54
55  /* Write the data. */
56#define UPDATE_memcpy(Data, Size) \
57  do {                            \
58    memcpy(Buffer, Data, Size);   \
59    Buffer += Size;               \
60  } while (0)
61  UPDATE_memcpy(Header,  PROFILE_HEADER_SIZE * sizeof(uint64_t));
62  UPDATE_memcpy(DataBegin,     DataSize      * sizeof(__llvm_profile_data));
63  UPDATE_memcpy(CountersBegin, CountersSize  * sizeof(uint64_t));
64  UPDATE_memcpy(NamesBegin,    NamesSize     * sizeof(char));
65  UPDATE_memcpy(Zeroes,        Padding       * sizeof(char));
66#undef UPDATE_memcpy
67
68  return 0;
69}
70