Home | History | Annotate | Line # | Download | only in profile
      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   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 
     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