blob: 27fa92611e607dc6fa68e44cea7f5a1c88d9ed72 [file] [log] [blame]
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +00001/*===- InstrProfilingFile.c - Write instrumentation to a file -------------===*\
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +00002|*
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 "InstrProfiling.h"
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +000011#include <stdio.h>
12#include <stdlib.h>
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000013#include <string.h>
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000014
Duncan P. N. Exon Smithcf4bb962014-03-21 18:29:19 +000015static int writeFile(FILE *File) {
16 const __llvm_profile_data *DataBegin = __llvm_profile_data_begin();
17 const __llvm_profile_data *DataEnd = __llvm_profile_data_end();
18 const uint64_t *CountersBegin = __llvm_profile_counters_begin();
19 const uint64_t *CountersEnd = __llvm_profile_counters_end();
20 const char *NamesBegin = __llvm_profile_names_begin();
21 const char *NamesEnd = __llvm_profile_names_end();
22
23 /* Calculate size of sections. */
24 const uint64_t DataSize = DataEnd - DataBegin;
25 const uint64_t CountersSize = CountersEnd - CountersBegin;
26 const uint64_t NamesSize = NamesEnd - NamesBegin;
27
28 /* Get rest of header data. */
29 const uint64_t Magic = __llvm_profile_get_magic();
30 const uint64_t Version = __llvm_profile_get_version();
31 const uint64_t CountersDelta = (uint64_t)CountersBegin;
32 const uint64_t NamesDelta = (uint64_t)NamesBegin;
33
34#define CHECK_fwrite(Data, Size, Length, File) \
35 do { if (fwrite(Data, Size, Length, File) != Length) return -1; } while (0)
36
37 /* Write the header. */
38 CHECK_fwrite(&Magic, sizeof(uint64_t), 1, File);
39 CHECK_fwrite(&Version, sizeof(uint64_t), 1, File);
40 CHECK_fwrite(&DataSize, sizeof(uint64_t), 1, File);
41 CHECK_fwrite(&CountersSize, sizeof(uint64_t), 1, File);
42 CHECK_fwrite(&NamesSize, sizeof(uint64_t), 1, File);
43 CHECK_fwrite(&CountersDelta, sizeof(uint64_t), 1, File);
44 CHECK_fwrite(&NamesDelta, sizeof(uint64_t), 1, File);
45
46 /* Write the data. */
47 CHECK_fwrite(DataBegin, sizeof(__llvm_profile_data), DataSize, File);
48 CHECK_fwrite(CountersBegin, sizeof(uint64_t), CountersSize, File);
49 CHECK_fwrite(NamesBegin, sizeof(char), NamesSize, File);
50
51#undef CHECK_fwrite
52
53 return 0;
54}
55
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +000056static int writeFileWithName(const char *OutputName) {
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000057 int RetVal;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000058 FILE *OutputFile;
59 if (!OutputName || !OutputName[0])
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000060 return -1;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000061 OutputFile = fopen(OutputName, "w");
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000062 if (!OutputFile)
63 return -1;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000064
Duncan P. N. Exon Smithcf4bb962014-03-21 18:29:19 +000065 RetVal = writeFile(OutputFile);
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000066
67 fclose(OutputFile);
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000068 return RetVal;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000069}
70
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000071static const char *CurrentFilename = NULL;
Duncan P. N. Exon Smith9edbae02014-03-20 20:00:44 +000072void __llvm_profile_set_filename(const char *Filename) {
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000073 CurrentFilename = Filename;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000074}
75
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000076int getpid(void);
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000077int __llvm_profile_write_file(void) {
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000078 char *AllocatedFilename = NULL;
79 int I, J;
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000080 int RetVal;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000081
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000082#define MAX_PID_SIZE 16
83 char PidChars[MAX_PID_SIZE] = { 0 };
84 int PidLength = 0;
85 int NumPids = 0;
86
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +000087 /* Get the filename. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000088 const char *Filename = CurrentFilename;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000089#define UPDATE_FILENAME(NextFilename) \
90 if (!Filename || !Filename[0]) Filename = NextFilename
91 UPDATE_FILENAME(getenv("LLVM_PROFILE_FILE"));
92 UPDATE_FILENAME("default.profdata");
93#undef UPDATE_FILENAME
94
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +000095 /* Check the filename for "%p", which indicates a pid-substitution. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000096 for (I = 0; Filename[I]; ++I)
97 if (Filename[I] == '%' && Filename[++I] == 'p')
98 if (!NumPids++) {
99 PidLength = snprintf(PidChars, MAX_PID_SIZE, "%d", getpid());
100 if (PidLength <= 0)
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000101 return -1;
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000102 }
103 if (NumPids) {
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000104 /* Allocate enough space for the substituted filename. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000105 AllocatedFilename = (char*)malloc(I + NumPids*(PidLength - 2) + 1);
106 if (!AllocatedFilename)
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000107 return -1;
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000108
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000109 /* Construct the new filename. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000110 for (I = 0, J = 0; Filename[I]; ++I)
111 if (Filename[I] == '%') {
112 if (Filename[++I] == 'p') {
113 memcpy(AllocatedFilename + J, PidChars, PidLength);
114 J += PidLength;
115 }
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000116 /* Drop any unknown substitutions. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000117 } else
118 AllocatedFilename[J++] = Filename[I];
119 AllocatedFilename[J] = 0;
120
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000121 /* Actually use the computed name. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000122 Filename = AllocatedFilename;
123 }
124
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000125 /* Write the file. */
126 RetVal = writeFileWithName(Filename);
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000127
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000128 /* Free the filename. */
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +0000129 if (AllocatedFilename)
130 free(AllocatedFilename);
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000131
132 return RetVal;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +0000133}
134
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000135static void writeFileWithoutReturn(void) {
136 __llvm_profile_write_file();
137}
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000138
139int __llvm_profile_register_write_file_atexit(void) {
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000140 static int HasBeenRegistered = 0;
141
Duncan P. N. Exon Smithbe0a5e12014-03-21 18:29:15 +0000142 if (HasBeenRegistered)
143 return 0;
144
145 HasBeenRegistered = 1;
146 return atexit(writeFileWithoutReturn);
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000147}