From d641b53f931bc6246cdb56aff3c1e00abd049bfe Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Tue, 28 Apr 2015 22:54:51 +0000 Subject: [PATCH] This change is the first of 3 patches to add support for specifying the profile output from the command line via -fprofile-instr-generate=, where the specified output path/file will be overridden by the LLVM_PROFILE_FILE environment variable. Several changes are made to the runtime to support this: Add a new interface __llvm_profile_override_default_filename that will set the profile output filename, but allows LLVM_PROFILE_FILE to override. This is the interface used by the new option. Refactor the pid-expansion done for LLVM_PROFILE_FILE into a separate routine that can be shared by the various filename setting routines (so that the filename from the option can also use the "%p" syntax). Move the truncation into setFilename, and only truncate if there is a new filename specified (to maintain support for appending to the same profile file in the case of multiple shared objects built with profiling). Move the handling for a NULL filename passed to __llvm_profile_set_filename and __llvm_profile_override_default_filename into the new setFilenamePossiblyWithPid routine. This now correctly resets the output file to default.profraw instead of NULL. The handling for a null LLVM_PROFILE_FILE (which should not reset) is done by caller setFilenameFromEnvironment. Patch by Teresa Johnson. llvm-svn: 236055 --- compiler-rt/lib/profile/InstrProfiling.h | 17 +++++++- compiler-rt/lib/profile/InstrProfilingFile.c | 59 ++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h index 2b1bd00..84b673c 100644 --- a/compiler-rt/lib/profile/InstrProfiling.h +++ b/compiler-rt/lib/profile/InstrProfiling.h @@ -62,7 +62,9 @@ uint64_t *__llvm_profile_end_counters(void); * * Writes to the file with the last name given to \a __llvm_profile_set_filename(), * or if it hasn't been called, the \c LLVM_PROFILE_FILE environment variable, - * or if that's not set, \c "default.profdata". + * or if that's not set, the last name given to + * \a __llvm_profile_override_default_filename(), or if that's not set, + * \c "default.profdata". */ int __llvm_profile_write_file(void); @@ -77,6 +79,19 @@ int __llvm_profile_write_file(void); */ void __llvm_profile_set_filename(const char *Name); +/*! + * \brief Set the filename for writing instrumentation data, unless the + * \c LLVM_PROFILE_FILE environment variable was set. + * + * Unless overridden, sets the filename to be used for subsequent calls to + * \a __llvm_profile_write_file(). + * + * \c Name is not copied, so it must remain valid. Passing NULL resets the + * filename logic to the default behaviour (unless the \c LLVM_PROFILE_FILE + * was set in which case it has no effect). + */ +void __llvm_profile_override_default_filename(const char *Name); + /*! \brief Register to write instrumentation data to file at exit. */ int __llvm_profile_register_write_file_atexit(void); diff --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c index d9acbbe..0102a25 100644 --- a/compiler-rt/lib/profile/InstrProfilingFile.c +++ b/compiler-rt/lib/profile/InstrProfilingFile.c @@ -76,14 +76,6 @@ static int writeFileWithName(const char *OutputName) { __attribute__((weak)) int __llvm_profile_OwnsFilename = 0; __attribute__((weak)) const char *__llvm_profile_CurrentFilename = NULL; -static void setFilename(const char *Filename, int OwnsFilename) { - if (__llvm_profile_OwnsFilename) - free(UNCONST(__llvm_profile_CurrentFilename)); - - __llvm_profile_CurrentFilename = Filename; - __llvm_profile_OwnsFilename = OwnsFilename; -} - static void truncateCurrentFile(void) { const char *Filename; FILE *File; @@ -99,19 +91,36 @@ static void truncateCurrentFile(void) { fclose(File); } -static void setDefaultFilename(void) { setFilename("default.profraw", 0); } +static void setFilename(const char *Filename, int OwnsFilename) { + /* Check if this is a new filename and therefore needs truncation. */ + int NewFile = !__llvm_profile_CurrentFilename || + (Filename && strcmp(Filename, __llvm_profile_CurrentFilename)); + if (__llvm_profile_OwnsFilename) + free(UNCONST(__llvm_profile_CurrentFilename)); + + __llvm_profile_CurrentFilename = Filename; + __llvm_profile_OwnsFilename = OwnsFilename; + + /* If not a new file, append to support profiling multiple shared objects. */ + if (NewFile) + truncateCurrentFile(); +} + +static void resetFilenameToDefault(void) { setFilename("default.profraw", 0); } int getpid(void); -static int setFilenameFromEnvironment(void) { - const char *Filename = getenv("LLVM_PROFILE_FILE"); +static int setFilenamePossiblyWithPid(const char *Filename) { #define MAX_PID_SIZE 16 char PidChars[MAX_PID_SIZE] = {0}; int NumPids = 0, PidLength = 0; char *Allocated; int I, J; - if (!Filename || !Filename[0]) - return -1; + /* Reset filename on NULL, except with env var which is checked by caller. */ + if (!Filename) { + resetFilenameToDefault(); + return 0; + } /* Check the filename for "%p", which indicates a pid-substitution. */ for (I = 0; Filename[I]; ++I) @@ -148,11 +157,20 @@ static int setFilenameFromEnvironment(void) { return 0; } +static int setFilenameFromEnvironment(void) { + const char *Filename = getenv("LLVM_PROFILE_FILE"); + + if (!Filename || !Filename[0]) + return -1; + + return setFilenamePossiblyWithPid(Filename); +} + static void setFilenameAutomatically(void) { if (!setFilenameFromEnvironment()) return; - setDefaultFilename(); + resetFilenameToDefault(); } __attribute__((visibility("hidden"))) @@ -163,13 +181,20 @@ void __llvm_profile_initialize_file(void) { /* Detect the filename and truncate. */ setFilenameAutomatically(); - truncateCurrentFile(); } __attribute__((visibility("hidden"))) void __llvm_profile_set_filename(const char *Filename) { - setFilename(Filename, 0); - truncateCurrentFile(); + setFilenamePossiblyWithPid(Filename); +} + +__attribute__((visibility("hidden"))) +void __llvm_profile_override_default_filename(const char *Filename) { + /* If the env var is set, skip setting filename from argument. */ + const char *Env_Filename = getenv("LLVM_PROFILE_FILE"); + if (Env_Filename && Env_Filename[0]) + return; + setFilenamePossiblyWithPid(Filename); } __attribute__((visibility("hidden"))) -- 2.7.4