Index: lib/profile/InstrProfiling.h =================================================================== --- lib/profile/InstrProfiling.h +++ lib/profile/InstrProfiling.h @@ -170,6 +170,12 @@ */ const char *__llvm_profile_get_path_prefix(); +/*! + * \brief Return filename (including path) of the profile data. + * 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: lib/profile/InstrProfilingFile.c =================================================================== --- lib/profile/InstrProfilingFile.c +++ 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,8 +85,8 @@ 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); @@ -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) { @@ -512,6 +516,32 @@ return Prefix; } +COMPILER_RT_VISIBILITY +const char *__llvm_profile_get_filename(void) { + int Length; + char *FilenameBuf, *ProfileFilename; + const char *Filename; + + if (lprofCurFilename.Filename) + return lprofCurFilename.Filename; + + Length = getCurFilenameLength(); + FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); + Filename = getCurFilename(FilenameBuf); + if (!Filename) + return "\0"; + + ProfileFilename = (char *)malloc(Length + 1); + if (!ProfileFilename) { + PROF_ERR("Failed to %s\n", "allocate memory."); + return "\0"; + } + memcpy(ProfileFilename, Filename, Length); + ProfileFilename[Length] = '\0'; + lprofCurFilename.Filename = ProfileFilename; + return ProfileFilename; +} + /* 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 Index: test/profile/instrprof-get-filename.c =================================================================== --- /dev/null +++ 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; +}