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