1 /*===- PGOProfiling.c - Support library for PGO instrumentation -----------===*\
3 |* The LLVM Compiler Infrastructure
5 |* This file is distributed under the University of Illinois Open Source
6 |* License. See LICENSE.TXT for details.
8 \*===----------------------------------------------------------------------===*/
13 #define I386_FREEBSD (defined(__FreeBSD__) && defined(__i386__))
19 #if !defined(_MSC_VER) && !I386_FREEBSD
24 typedef unsigned int uint32_t;
25 typedef unsigned int uint64_t;
27 /* System headers define 'size_t' incorrectly on x64 FreeBSD (prior to
28 * FreeBSD 10, r232261) when compiled in 32-bit mode.
31 typedef unsigned int uint32_t;
32 typedef unsigned long long uint64_t;
35 typedef struct __ProfileData
{
36 const uint32_t NameSize
;
37 const uint32_t NumCounters
;
38 const char *const Name
;
39 const uint64_t *const Counters
;
42 /* TODO: Calculate these with linker magic. */
43 static __ProfileData
*First
= NULL
;
44 static __ProfileData
*Final
= NULL
;
46 * \brief Register an instrumented function.
48 * Calls to this are emitted by clang with -fprofile-instr-generate. Such
49 * calls are only required (and only emitted) on targets where we haven't
50 * implemented linker magic to find the bounds of the section.
52 * For now, that's all targets.
54 void __llvm_pgo_register_function(void *Data_
) {
55 /* TODO: Only emit this function if we can't use linker magic. */
56 __ProfileData
*Data
= (__ProfileData
*)Data_
;
57 if (!First
|| Data
< First
)
59 if (!Final
|| Data
> Final
)
63 /*! \brief Get the first instrumentation record. */
64 static __ProfileData
*getFirst() {
65 /* TODO: Use extern + linker magic instead of a static variable. */
69 /*! \brief Get the last instrumentation record. */
70 static __ProfileData
*getLast() {
71 /* TODO: Use extern + linker magic instead of a static variable. */
75 /* TODO: void __llvm_pgo_get_size_for_buffer(void); */
76 /* TODO: void __llvm_pgo_write_buffer(char *Buffer); */
78 static void writeFunction(FILE *OutputFile
, const __ProfileData
*Data
) {
79 /* TODO: Requires libc: break requirement by writing directly to a buffer
80 * instead of a FILE stream.
83 for (I
= 0; I
< Data
->NameSize
; ++I
)
84 fputc(Data
->Name
[I
], OutputFile
);
85 fprintf(OutputFile
, " %u\n", Data
->NumCounters
);
86 for (I
= 0; I
< Data
->NumCounters
; ++I
)
87 fprintf(OutputFile
, "%" PRIu64
"\n", Data
->Counters
[I
]);
88 fprintf(OutputFile
, "\n");
91 /*! \brief Write instrumentation data to the given file. */
92 void __llvm_pgo_write_file(const char *OutputName
) {
93 /* TODO: Requires libc: move to separate translation unit. */
96 if (!OutputName
|| !OutputName
[0])
98 OutputFile
= fopen(OutputName
, "w");
99 if (!OutputFile
) return;
101 /* TODO: mmap file to buffer of size __llvm_pgo_get_size_for_buffer() and
102 * call __llvm_pgo_write_buffer().
104 for (I
= getFirst(), E
= getLast(); I
!= E
; ++I
)
105 writeFunction(OutputFile
, I
);
110 /*! \brief Write instrumentation data to the default file. */
111 void __llvm_pgo_write_default_file() {
112 /* TODO: Requires libc: move to separate translation unit. */
113 const char *OutputName
= getenv("LLVM_PROFILE_FILE");
114 if (OutputName
== NULL
|| OutputName
[0] == '\0')
115 OutputName
= "default.profdata";
116 __llvm_pgo_write_file(OutputName
);
120 * \brief Register to write instrumentation data to the default file at exit.
122 void __llvm_pgo_register_write_atexit() {
123 /* TODO: Requires libc: move to separate translation unit. */
124 static int HasBeenRegistered
= 0;
126 if (!HasBeenRegistered
) {
127 HasBeenRegistered
= 1;
128 atexit(__llvm_pgo_write_default_file
);