blob: 723952f0856164ae60f97bf9d75ab10e0333ec0b [file] [log] [blame]
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +00001/*===- InstrProfilingExtras.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 "InstrProfiling.h"
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000011#include <string.h>
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000012
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000013static int __llvm_profile_write_file_with_name(const char *OutputName) {
14 int RetVal;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000015 FILE *OutputFile;
16 if (!OutputName || !OutputName[0])
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000017 return -1;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000018 OutputFile = fopen(OutputName, "w");
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000019 if (!OutputFile)
20 return -1;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000021
Duncan P. N. Exon Smith9edbae02014-03-20 20:00:44 +000022 /* TODO: mmap file to buffer of size __llvm_profile_get_size_for_buffer() and
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000023 * pass the buffer in, instead of the file.
24 */
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000025 RetVal = __llvm_profile_write_buffer(OutputFile);
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000026
27 fclose(OutputFile);
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000028 return RetVal;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000029}
30
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000031static const char *CurrentFilename = NULL;
Duncan P. N. Exon Smith9edbae02014-03-20 20:00:44 +000032void __llvm_profile_set_filename(const char *Filename) {
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000033 CurrentFilename = Filename;
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000034}
35
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000036int getpid(void);
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000037int __llvm_profile_write_file(void) {
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000038 char *AllocatedFilename = NULL;
39 int I, J;
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000040 int RetVal;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000041
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000042#define MAX_PID_SIZE 16
43 char PidChars[MAX_PID_SIZE] = { 0 };
44 int PidLength = 0;
45 int NumPids = 0;
46
47 // Get the filename.
48 const char *Filename = CurrentFilename;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000049#define UPDATE_FILENAME(NextFilename) \
50 if (!Filename || !Filename[0]) Filename = NextFilename
51 UPDATE_FILENAME(getenv("LLVM_PROFILE_FILE"));
52 UPDATE_FILENAME("default.profdata");
53#undef UPDATE_FILENAME
54
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000055 // Check the filename for "%p", which indicates a pid-substitution.
56 for (I = 0; Filename[I]; ++I)
57 if (Filename[I] == '%' && Filename[++I] == 'p')
58 if (!NumPids++) {
59 PidLength = snprintf(PidChars, MAX_PID_SIZE, "%d", getpid());
60 if (PidLength <= 0)
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000061 return -1;
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000062 }
63 if (NumPids) {
64 // Allocate enough space for the substituted filename.
65 AllocatedFilename = (char*)malloc(I + NumPids*(PidLength - 2) + 1);
66 if (!AllocatedFilename)
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000067 return -1;
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000068
69 // Construct the new filename.
70 for (I = 0, J = 0; Filename[I]; ++I)
71 if (Filename[I] == '%') {
72 if (Filename[++I] == 'p') {
73 memcpy(AllocatedFilename + J, PidChars, PidLength);
74 J += PidLength;
75 }
76 // Drop any unknown substitutions.
77 } else
78 AllocatedFilename[J++] = Filename[I];
79 AllocatedFilename[J] = 0;
80
81 // Actually use the computed name.
82 Filename = AllocatedFilename;
83 }
84
85 // Write the file.
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000086 RetVal = __llvm_profile_write_file_with_name(Filename);
Duncan P. N. Exon Smithe5edc882014-03-21 00:27:48 +000087
88 // Free the filename.
89 if (AllocatedFilename)
90 free(AllocatedFilename);
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000091
92 return RetVal;
Duncan P. N. Exon Smith54cc0e22014-03-20 19:23:55 +000093}
94
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +000095static void writeFileWithoutReturn(void) {
96 __llvm_profile_write_file();
97}
Duncan P. N. Exon Smith71704752014-03-20 20:55:00 +000098void __llvm_profile_register_write_file_atexit(void) {
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +000099 static int HasBeenRegistered = 0;
100
101 if (!HasBeenRegistered) {
102 HasBeenRegistered = 1;
Duncan P. N. Exon Smith4543aac2014-03-21 00:27:50 +0000103 atexit(writeFileWithoutReturn);
Duncan P. N. Exon Smith8353a262014-03-19 22:10:27 +0000104 }
105}