1 /*===- PGOProfiling.c - Support library for PGO instrumentation -----------===*\
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 <inttypes.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #ifndef _MSC_VER
15 #include <stdint.h>
16 #else
17 typedef unsigned int uint32_t;
18 typedef unsigned int uint64_t;
19 #endif
20
21 static FILE *OutputFile = NULL;
22
23 /*
24 * A list of functions to write out the data.
25 */
26 typedef void (*writeout_fn)();
27
28 struct writeout_fn_node {
29 writeout_fn fn;
30 struct writeout_fn_node *next;
31 };
32
33 static struct writeout_fn_node *writeout_fn_head = NULL;
34 static struct writeout_fn_node *writeout_fn_tail = NULL;
35
llvm_pgo_emit(const char * MangledName,uint32_t NumCounters,uint64_t * Counters)36 void llvm_pgo_emit(const char *MangledName, uint32_t NumCounters,
37 uint64_t *Counters) {
38 uint32_t i;
39 fprintf(OutputFile, "%s %u\n", MangledName, NumCounters);
40 for (i = 0; i < NumCounters; ++i)
41 fprintf(OutputFile, "%" PRIu64 "\n", Counters[i]);
42 fprintf(OutputFile, "\n");
43 }
44
llvm_pgo_register_writeout_function(writeout_fn fn)45 void llvm_pgo_register_writeout_function(writeout_fn fn) {
46 struct writeout_fn_node *new_node = malloc(sizeof(struct writeout_fn_node));
47 new_node->fn = fn;
48 new_node->next = NULL;
49
50 if (!writeout_fn_head) {
51 writeout_fn_head = writeout_fn_tail = new_node;
52 } else {
53 writeout_fn_tail->next = new_node;
54 writeout_fn_tail = new_node;
55 }
56 }
57
llvm_pgo_writeout_files()58 void llvm_pgo_writeout_files() {
59 const char *OutputName = getenv("LLVM_PROFILE_FILE");
60 if (OutputName == NULL || OutputName[0] == '\0')
61 OutputName = "default.profdata";
62 OutputFile = fopen(OutputName, "w");
63 if (!OutputFile) return;
64
65 while (writeout_fn_head) {
66 struct writeout_fn_node *node = writeout_fn_head;
67 writeout_fn_head = writeout_fn_head->next;
68 node->fn();
69 free(node);
70 }
71
72 fclose(OutputFile);
73 }
74
llvm_pgo_init(writeout_fn wfn)75 void llvm_pgo_init(writeout_fn wfn) {
76 static int atexit_ran = 0;
77
78 if (wfn)
79 llvm_pgo_register_writeout_function(wfn);
80
81 if (atexit_ran == 0) {
82 atexit_ran = 1;
83 atexit(llvm_pgo_writeout_files);
84 }
85 }
86