Index: compiler-rt/trunk/lib/profile/InstrProfiling.h =================================================================== --- compiler-rt/trunk/lib/profile/InstrProfiling.h +++ compiler-rt/trunk/lib/profile/InstrProfiling.h @@ -170,6 +170,14 @@ */ const char *__llvm_profile_get_path_prefix(); +/*! + * \brief Return filename (including path) of the profile data. Note that if the + * user calls __llvm_profile_set_filename later after invoking this interface, + * the actual file name may differ from what is returned here. + * Side-effect: this API call will invoke malloc with dynamic memory allocation. + */ +const char *__llvm_profile_get_filename(); + /*! \brief Get the magic token for the file format. */ uint64_t __llvm_profile_get_magic(void); Index: compiler-rt/trunk/lib/profile/InstrProfilingFile.c =================================================================== --- compiler-rt/trunk/lib/profile/InstrProfilingFile.c +++ compiler-rt/trunk/lib/profile/InstrProfilingFile.c @@ -69,6 +69,7 @@ * by runtime. */ unsigned OwnsFilenamePat; const char *ProfilePathPrefix; + const char *Filename; char PidChars[MAX_PID_SIZE]; char Hostname[COMPILER_RT_MAX_HOSTLEN]; unsigned NumPids; @@ -84,11 +85,11 @@ ProfileNameSpecifier PNS; } lprofFilename; -COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0}, - 0, 0, 0, PNS_unknown}; +COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, 0, {0}, + {0}, 0, 0, 0, PNS_unknown}; static int getCurFilenameLength(); -static const char *getCurFilename(char *FilenameBuf); +static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf); static unsigned doMerging() { return lprofCurFilename.MergePoolSize; } /* Return 1 if there is an error, otherwise return 0. */ @@ -266,7 +267,7 @@ Length = getCurFilenameLength(); FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); - Filename = getCurFilename(FilenameBuf); + Filename = getCurFilename(FilenameBuf, 0); if (!Filename) return; @@ -311,9 +312,12 @@ char *Hostname = &lprofCurFilename.Hostname[0]; int MergingEnabled = 0; - /* Clean up cached prefix. */ + /* Clean up cached prefix and filename. */ if (lprofCurFilename.ProfilePathPrefix) free((void *)lprofCurFilename.ProfilePathPrefix); + if (lprofCurFilename.Filename) + free((void *)lprofCurFilename.Filename); + memset(&lprofCurFilename, 0, sizeof(lprofCurFilename)); if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) { @@ -428,17 +432,25 @@ /* Return the pointer to the current profile file name (after substituting * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer * to store the resulting filename. If no substitution is needed, the - * current filename pattern string is directly returned. */ -static const char *getCurFilename(char *FilenameBuf) { - int I, J, PidLength, HostNameLength; + * current filename pattern string is directly returned, unless ForceUseBuf + * is enabled. */ +static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) { + int I, J, PidLength, HostNameLength, FilenamePatLength; const char *FilenamePat = lprofCurFilename.FilenamePat; if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0]) return 0; if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts || - lprofCurFilename.MergePoolSize)) - return lprofCurFilename.FilenamePat; + lprofCurFilename.MergePoolSize)) { + if (!ForceUseBuf) + return lprofCurFilename.FilenamePat; + + FilenamePatLength = strlen(lprofCurFilename.FilenamePat); + memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength); + FilenameBuf[FilenamePatLength] = '\0'; + return FilenameBuf; + } PidLength = strlen(lprofCurFilename.PidChars); HostNameLength = strlen(lprofCurFilename.Hostname); @@ -492,7 +504,7 @@ Length = getCurFilenameLength(); FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); - Filename = getCurFilename(FilenameBuf); + Filename = getCurFilename(FilenameBuf, 0); if (!Filename) return "\0"; @@ -512,6 +524,29 @@ return Prefix; } +COMPILER_RT_VISIBILITY +const char *__llvm_profile_get_filename(void) { + int Length; + char *FilenameBuf; + const char *Filename; + + if (lprofCurFilename.Filename) + return lprofCurFilename.Filename; + + Length = getCurFilenameLength(); + FilenameBuf = (char *)malloc(Length + 1); + if (!FilenameBuf) { + PROF_ERR("Failed to %s\n", "allocate memory."); + return "\0"; + } + Filename = getCurFilename(FilenameBuf, 1); + if (!Filename) + return "\0"; + + lprofCurFilename.Filename = FilenameBuf; + return FilenameBuf; +} + /* This method is invoked by the runtime initialization hook * InstrProfilingRuntime.o if it is linked in. Both user specified * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE @@ -568,7 +603,7 @@ Length = getCurFilenameLength(); FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); - Filename = getCurFilename(FilenameBuf); + Filename = getCurFilename(FilenameBuf, 0); /* Check the filename. */ if (!Filename) { Index: compiler-rt/trunk/test/profile/instrprof-get-filename.c =================================================================== --- compiler-rt/trunk/test/profile/instrprof-get-filename.c +++ compiler-rt/trunk/test/profile/instrprof-get-filename.c @@ -0,0 +1,39 @@ +// Test __llvm_profile_get_filename. +// RUN: %clang_pgogen -O2 -o %t %s +// RUN: %run %t + +#include +#include + +const char *__llvm_profile_get_filename(); +void __llvm_profile_set_filename(const char *); + +int main(int argc, const char *argv[]) { + int i; + const char *filename; + const char *new_filename = "/path/to/test.profraw"; + + filename = __llvm_profile_get_filename(); + if (strncmp(filename, "default_", 8)) { + fprintf(stderr, + "Error: got filename %s, expected it to start with 'default_'\n", + filename); + return 1; + } + if (strcmp(filename + strlen(filename) - strlen(".profraw"), ".profraw")) { + fprintf(stderr, + "Error: got filename %s, expected it to end with '.profraw'\n", + filename); + return 1; + } + + __llvm_profile_set_filename(new_filename); + filename = __llvm_profile_get_filename(); + if (strcmp(filename, new_filename)) { + fprintf(stderr, "Error: got filename %s, expected '%s'\n", filename, + new_filename); + return 1; + } + + return 0; +}