summaryrefslogtreecommitdiff
path: root/lib/profile/InstrProfiling.c
blob: 5676f5ac05e30560d8ac6923735c00f7821c85ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*===- InstrProfiling.c - Support library for PGO instrumentation ---------===*\
|*
|*                     The LLVM Compiler Infrastructure
|*
|* This file is distributed under the University of Illinois Open Source
|* License. See LICENSE.TXT for details.
|*
\*===----------------------------------------------------------------------===*/

#include "InstrProfiling.h"

/* TODO: Calculate these with linker magic. */
static __llvm_pgo_data *First = NULL;
static __llvm_pgo_data *Last = NULL;

/*!
 * \brief Register an instrumented function.
 *
 * Calls to this are emitted by clang with -fprofile-instr-generate.  Such
 * calls are only required (and only emitted) on targets where we haven't
 * implemented linker magic to find the bounds of the section.
 *
 * For now, that's all targets.
 */
void __llvm_pgo_register_function(void *Data_) {
  /* TODO: Only emit this function if we can't use linker magic. */
  __llvm_pgo_data *Data = (__llvm_pgo_data*)Data_;
  if (!First || Data < First)
    First = Data;
  if (!Last || Data >= Last)
    Last = Data + 1;
}

/*! \brief Get the first instrumentation record. */
static __llvm_pgo_data *getFirst() {
  /* TODO: Use extern + linker magic instead of a static variable. */
  return First;
}

/*! \brief Get the last instrumentation record. */
static __llvm_pgo_data *getLast() {
  /* TODO: Use extern + linker magic instead of a static variable. */
  return Last;
}

/* TODO: void __llvm_pgo_get_size_for_buffer(void);  */

static void writeFunction(FILE *OutputFile, const __llvm_pgo_data *Data) {
  /* TODO: Requires libc: break requirement by writing directly to a buffer
   * instead of a FILE stream.
   */
  uint32_t I;
  for (I = 0; I < Data->NameSize; ++I)
    fputc(Data->Name[I], OutputFile);
  fprintf(OutputFile, "\n%" PRIu64 "\n%u\n", Data->FuncHash, Data->NumCounters);
  for (I = 0; I < Data->NumCounters; ++I)
    fprintf(OutputFile, "%" PRIu64 "\n", Data->Counters[I]);
  fprintf(OutputFile, "\n");
}

void __llvm_pgo_write_buffer(FILE *OutputFile) {
  /* TODO: Requires libc: break requirement by taking a char* buffer instead of
   * a FILE stream.
   */
  __llvm_pgo_data *I, *E;

  for (I = getFirst(), E = getLast(); I != E; ++I)
    writeFunction(OutputFile, I);
}