fix an oversight which caused us to compile the testcase (and other
[oota-llvm.git] / runtime / libprofile / GCDAProfiling.c
1 /*===- GCDAProfiling.c - Support library for GCDA file emission -----------===*\
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 |* This file implements the call back routines for the gcov profiling
11 |* instrumentation pass. Link against this library when running code through
12 |* the -insert-gcov-profiling LLVM pass.
13 |*
14 |* We emit files in a corrupt version of GCOV's "gcda" file format. These files
15 |* are only close enough that LCOV will happily parse them. Anything that lcov
16 |* ignores is missing.
17 |*
18 \*===----------------------------------------------------------------------===*/
19
20 #include "llvm/Support/DataTypes.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 /* #define DEBUG_GCDAPROFILING */
26
27 /*
28  * --- GCOV file format I/O primitives ---
29  */
30
31 static FILE *output_file = NULL;
32
33 static void write_int32(uint32_t i) {
34   fwrite(&i, 4, 1, output_file);
35 }
36
37 static void write_int64(uint64_t i) {
38   uint32_t lo, hi;
39   lo = i >>  0;
40   hi = i >> 32;
41
42   write_int32(lo);
43   write_int32(hi);
44 }
45
46 /*
47  * --- LLVM line counter API ---
48  */
49
50 /* A file in this case is a translation unit. Each .o file built with line
51  * profiling enabled will emit to a different file. Only one file may be
52  * started at a time.
53  */
54 void llvm_gcda_start_file(const char *filename) {
55   output_file = fopen(filename, "w+");
56
57   /* gcda file, version 404*, stamp LLVM. */
58   fwrite("adcg*404MVLL", 12, 1, output_file);
59
60 #ifdef DEBUG_GCDAPROFILING
61   printf("[%s]\n", filename);
62 #endif
63 }
64
65 void llvm_gcda_emit_function(uint32_t ident) {
66 #ifdef DEBUG_GCDAPROFILING
67   printf("function id=%x\n", ident);
68 #endif
69
70   /* function tag */  
71   fwrite("\0\0\0\1", 4, 1, output_file);
72   write_int32(2);
73   write_int32(ident);
74   write_int32(0);
75 }
76
77 void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {
78   uint32_t i;
79   /* counter #1 (arcs) tag */
80   fwrite("\0\0\xa1\1", 4, 1, output_file);
81   write_int32(num_counters * 2);
82   for (i = 0; i < num_counters; ++i) {
83     write_int64(counters[i]);
84   }
85
86 #ifdef DEBUG_GCDAPROFILING
87   printf("  %u arcs\n", num_counters);
88   for (i = 0; i < num_counters; ++i) {
89     printf("  %llu\n", (unsigned long long)counters[i]);
90   }
91 #endif
92 }
93
94 void llvm_gcda_end_file() {
95   /* Write out EOF record. */
96   fwrite("\0\0\0\0\0\0\0\0", 8, 1, output_file);
97   fclose(output_file);
98   output_file = NULL;
99
100 #ifdef DEBUG_GCDAPROFILING
101   printf("-----\n");
102 #endif
103 }