xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/profile/PGOProfiling.c (revision dd255ccea4286b0c44fa8fd48a9a19a768afe8e1)
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 
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 
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 
58 void llvm_pgo_writeout_files() {
59   OutputFile = fopen("pgo-data", "w");
60   if (!OutputFile) return;
61 
62   while (writeout_fn_head) {
63     struct writeout_fn_node *node = writeout_fn_head;
64     writeout_fn_head = writeout_fn_head->next;
65     node->fn();
66     free(node);
67   }
68 
69   fclose(OutputFile);
70 }
71 
72 void llvm_pgo_init(writeout_fn wfn) {
73   static int atexit_ran = 0;
74 
75   if (wfn)
76     llvm_pgo_register_writeout_function(wfn);
77 
78   if (atexit_ran == 0) {
79     atexit_ran = 1;
80     atexit(llvm_pgo_writeout_files);
81   }
82 }
83