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