diff options
Diffstat (limited to 'lib/profile')
-rw-r--r-- | lib/profile/CMakeLists.txt | 5 | ||||
-rw-r--r-- | lib/profile/GCDAProfiling.c | 4 | ||||
-rw-r--r-- | lib/profile/InstrProfData.inc | 11 | ||||
-rw-r--r-- | lib/profile/InstrProfiling.c | 16 | ||||
-rw-r--r-- | lib/profile/InstrProfiling.h | 63 | ||||
-rw-r--r-- | lib/profile/InstrProfilingFile.c | 162 | ||||
-rw-r--r-- | lib/profile/InstrProfilingInternal.h | 18 | ||||
-rw-r--r-- | lib/profile/InstrProfilingPort.h | 6 | ||||
-rw-r--r-- | lib/profile/InstrProfilingRuntime.cc | 3 | ||||
-rw-r--r-- | lib/profile/InstrProfilingUtil.c | 39 | ||||
-rw-r--r-- | lib/profile/InstrProfilingUtil.h | 21 | ||||
-rw-r--r-- | lib/profile/InstrProfilingValue.c | 2 | ||||
-rw-r--r-- | lib/profile/WindowsMMap.c | 3 |
13 files changed, 259 insertions, 94 deletions
diff --git a/lib/profile/CMakeLists.txt b/lib/profile/CMakeLists.txt index ccf79d7e72675..006285b34943c 100644 --- a/lib/profile/CMakeLists.txt +++ b/lib/profile/CMakeLists.txt @@ -38,8 +38,7 @@ int main() { " COMPILER_RT_TARGET_HAS_FCNTL_LCK) -add_custom_target(profile) -set_target_properties(profile PROPERTIES FOLDER "Compiler-RT Misc") +add_compiler_rt_component(profile) set(PROFILE_SOURCES GCDAProfiling.c @@ -99,5 +98,3 @@ else() SOURCES ${PROFILE_SOURCES} PARENT_TARGET profile) endif() - -add_dependencies(compiler-rt profile) diff --git a/lib/profile/GCDAProfiling.c b/lib/profile/GCDAProfiling.c index 2756084f5fd3d..138af6ec40334 100644 --- a/lib/profile/GCDAProfiling.c +++ b/lib/profile/GCDAProfiling.c @@ -20,7 +20,6 @@ |* \*===----------------------------------------------------------------------===*/ -#include "InstrProfilingInternal.h" #include "InstrProfilingPort.h" #include "InstrProfilingUtil.h" @@ -35,6 +34,9 @@ #else #include <sys/mman.h> #include <sys/file.h> +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif #endif #if defined(__FreeBSD__) && defined(__i386__) diff --git a/lib/profile/InstrProfData.inc b/lib/profile/InstrProfData.inc index 93d14ac4f6f9c..f7c22d10763c5 100644 --- a/lib/profile/InstrProfData.inc +++ b/lib/profile/InstrProfData.inc @@ -72,7 +72,7 @@ #endif INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ - IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName())))) + IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName())))) INSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ Inc->getHash()->getZExtValue())) @@ -204,7 +204,7 @@ COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ #else COVMAP_FUNC_RECORD(const int64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ - llvm::IndexedInstrProf::ComputeHash(NameValue))) + llvm::IndexedInstrProf::ComputeHash(NameValue))) #endif COVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \ llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx),\ @@ -603,7 +603,12 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define VARIANT_MASKS_ALL 0xff00000000000000ULL #define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) #define VARIANT_MASK_IR_PROF (0x1ULL << 56) -#define IR_LEVEL_PROF_VERSION_VAR __llvm_profile_raw_version +#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version +#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime + +/* The variable that holds the name of the profile data + * specified via command line. */ +#define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename /* Runtime section names and name strings. */ #define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data diff --git a/lib/profile/InstrProfiling.c b/lib/profile/InstrProfiling.c index c763a44233a0e..6828a3d27f34c 100644 --- a/lib/profile/InstrProfiling.c +++ b/lib/profile/InstrProfiling.c @@ -16,15 +16,26 @@ #define INSTR_PROF_VALUE_PROF_DATA #include "InstrProfData.inc" -COMPILER_RT_VISIBILITY char *(*GetEnvHook)(const char *) = 0; -COMPILER_RT_WEAK uint64_t __llvm_profile_raw_version = INSTR_PROF_RAW_VERSION; +COMPILER_RT_WEAK uint64_t INSTR_PROF_RAW_VERSION_VAR = INSTR_PROF_RAW_VERSION; + +COMPILER_RT_WEAK char INSTR_PROF_PROFILE_NAME_VAR[1] = {0}; COMPILER_RT_VISIBILITY uint64_t __llvm_profile_get_magic(void) { return sizeof(void *) == sizeof(uint64_t) ? (INSTR_PROF_RAW_MAGIC_64) : (INSTR_PROF_RAW_MAGIC_32); } +static unsigned ProfileDumped = 0; + +COMPILER_RT_VISIBILITY unsigned lprofProfileDumped() { + return ProfileDumped; +} + +COMPILER_RT_VISIBILITY void lprofSetProfileDumped() { + ProfileDumped = 1; +} + /* Return the number of bytes needed to add to SizeInBytes to make it * the result a multiple of 8. */ @@ -66,4 +77,5 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) { } } } + ProfileDumped = 0; } diff --git a/lib/profile/InstrProfiling.h b/lib/profile/InstrProfiling.h index b23bed8ea3a84..945f1c4ac38d8 100644 --- a/lib/profile/InstrProfiling.h +++ b/lib/profile/InstrProfiling.h @@ -112,35 +112,43 @@ void INSTR_PROF_VALUE_PROF_FUNC( * 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, the last name given to - * \a __llvm_profile_override_default_filename(), or if that's not set, - * \c "default.profraw". + * or if that's not set, the last name set to INSTR_PROF_PROFILE_NAME_VAR, + * or if that's not set, \c "default.profraw". */ int __llvm_profile_write_file(void); /*! - * \brief Set the filename for writing instrumentation data. + * \brief this is a wrapper interface to \c __llvm_profile_write_file. + * After this interface is invoked, a arleady dumped flag will be set + * so that profile won't be dumped again during program exit. + * Invocation of interface __llvm_profile_reset_counters will clear + * the flag. This interface is designed to be used to collect profile + * data from user selected hot regions. The use model is + * __llvm_profile_reset_counters(); + * ... hot region 1 + * __llvm_profile_dump(); + * .. some other code + * __llvm_profile_reset_counters(); + * ... hot region 2 + * __llvm_profile_dump(); * - * 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. + * It is expected that on-line profile merging is on with \c %m specifier + * used in profile filename . If merging is not turned on, user is expected + * to invoke __llvm_profile_set_filename to specify different profile names + * for different regions before dumping to avoid profile write clobbering. */ -void __llvm_profile_set_filename(const char *Name); +int __llvm_profile_dump(void); /*! - * \brief Set the filename for writing instrumentation data, unless the - * \c LLVM_PROFILE_FILE environment variable was set. + * \brief Set the filename for writing instrumentation data. * - * Unless overridden, sets the filename to be used for subsequent calls to + * 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). + * filename logic to the default behaviour. */ -void __llvm_profile_override_default_filename(const char *Name); +void __llvm_profile_set_filename(const char *Name); /*! \brief Register to write instrumentation data to file at exit. */ int __llvm_profile_register_write_file_atexit(void); @@ -148,6 +156,16 @@ int __llvm_profile_register_write_file_atexit(void); /*! \brief Initialize file handling. */ void __llvm_profile_initialize_file(void); +/*! + * \brief Return path prefix (excluding the base filename) of the profile data. + * This is useful for users using \c -fprofile-generate=./path_prefix who do + * not care about the default raw profile name. It is also useful to collect + * more than more profile data files dumped in the same directory (Online + * merge mode is turned on for instrumented programs with shared libs). + * Side-effect: this API call will invoke malloc with dynamic memory allocation. + */ +const char *__llvm_profile_get_path_prefix(); + /*! \brief Get the magic token for the file format. */ uint64_t __llvm_profile_get_magic(void); @@ -166,8 +184,8 @@ uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin, * Note that this variable's visibility needs to be hidden so that the * definition of this variable in an instrumented shared library won't * affect runtime initialization decision of the main program. - */ -COMPILER_RT_VISIBILITY extern int __llvm_profile_runtime; + * __llvm_profile_profile_runtime. */ +COMPILER_RT_VISIBILITY extern int INSTR_PROF_PROFILE_RUNTIME_VAR; /*! * This variable is defined in InstrProfiling.c. Its main purpose is to @@ -179,6 +197,13 @@ COMPILER_RT_VISIBILITY extern int __llvm_profile_runtime; * main program are expected to be instrumented in the same way), there is * no need for this variable to be hidden. */ -extern uint64_t __llvm_profile_raw_version; +extern uint64_t INSTR_PROF_RAW_VERSION_VAR; /* __llvm_profile_raw_version */ + +/*! + * This variable is a weak symbol defined in InstrProfiling.c. It allows + * compiler instrumentation to provide overriding definition with value + * from compiler command line. This variable has default visibility. + */ +extern char INSTR_PROF_PROFILE_NAME_VAR[1]; /* __llvm_profile_filename. */ #endif /* PROFILE_INSTRPROFILING_H_ */ diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c index 32762d14eef2e..f82080c98aac4 100644 --- a/lib/profile/InstrProfilingFile.c +++ b/lib/profile/InstrProfilingFile.c @@ -59,10 +59,14 @@ static const char *getPNSStr(ProfileNameSpecifier PNS) { } #define MAX_PID_SIZE 16 -/* Data structure holding the result of parsed filename pattern. */ +/* Data structure holding the result of parsed filename pattern. */ typedef struct lprofFilename { /* File name string possibly with %p or %h specifiers. */ const char *FilenamePat; + /* A flag indicating if FilenamePat's memory is allocated + * by runtime. */ + unsigned OwnsFilenamePat; + const char *ProfilePathPrefix; char PidChars[MAX_PID_SIZE]; char Hostname[COMPILER_RT_MAX_HOSTLEN]; unsigned NumPids; @@ -78,7 +82,8 @@ typedef struct lprofFilename { ProfileNameSpecifier PNS; } lprofFilename; -lprofFilename lprofCurFilename = {0, {0}, {0}, 0, 0, 0, PNS_unknown}; +COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0}, + 0, 0, 0, PNS_unknown}; int getpid(void); static int getCurFilenameLength(); @@ -229,16 +234,17 @@ static void truncateCurrentFile(void) { return; /* Create the directory holding the file, if needed. */ - if (strchr(Filename, DIR_SEPARATOR) -#if defined(DIR_SEPARATOR_2) - || strchr(Filename, DIR_SEPARATOR_2) -#endif - ) { + if (lprofFindFirstDirSeparator(Filename)) { char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1); strncpy(Copy, Filename, Length + 1); __llvm_profile_recursive_mkdir(Copy); } + /* By pass file truncation to allow online raw profile + * merging. */ + if (lprofCurFilename.MergePoolSize) + return; + /* Truncate the file. Later we'll reopen and append. */ File = fopen(Filename, "w"); if (!File) @@ -248,6 +254,9 @@ static void truncateCurrentFile(void) { static const char *DefaultProfileName = "default.profraw"; static void resetFilenameToDefault(void) { + if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) { + free((void *)lprofCurFilename.FilenamePat); + } memset(&lprofCurFilename, 0, sizeof(lprofCurFilename)); lprofCurFilename.FilenamePat = DefaultProfileName; lprofCurFilename.PNS = PNS_default; @@ -263,31 +272,46 @@ static int containsMergeSpecifier(const char *FilenamePat, int I) { /* Parses the pattern string \p FilenamePat and stores the result to * lprofcurFilename structure. */ -static int parseFilenamePattern(const char *FilenamePat) { +static int parseFilenamePattern(const char *FilenamePat, + unsigned CopyFilenamePat) { int NumPids = 0, NumHosts = 0, I; char *PidChars = &lprofCurFilename.PidChars[0]; char *Hostname = &lprofCurFilename.Hostname[0]; int MergingEnabled = 0; - lprofCurFilename.FilenamePat = FilenamePat; + /* Clean up cached prefix. */ + if (lprofCurFilename.ProfilePathPrefix) + free((void *)lprofCurFilename.ProfilePathPrefix); + memset(&lprofCurFilename, 0, sizeof(lprofCurFilename)); + + if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) { + free((void *)lprofCurFilename.FilenamePat); + } + + if (!CopyFilenamePat) + lprofCurFilename.FilenamePat = FilenamePat; + else { + lprofCurFilename.FilenamePat = strdup(FilenamePat); + lprofCurFilename.OwnsFilenamePat = 1; + } /* Check the filename for "%p", which indicates a pid-substitution. */ for (I = 0; FilenamePat[I]; ++I) if (FilenamePat[I] == '%') { if (FilenamePat[++I] == 'p') { if (!NumPids++) { if (snprintf(PidChars, MAX_PID_SIZE, "%d", getpid()) <= 0) { - PROF_WARN( - "Unable to parse filename pattern %s. Using the default name.", - FilenamePat); + PROF_WARN("Unable to get pid for filename pattern %s. Using the " + "default name.", + FilenamePat); return -1; } } } else if (FilenamePat[I] == 'h') { if (!NumHosts++) if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) { - PROF_WARN( - "Unable to parse filename pattern %s. Using the default name.", - FilenamePat); + PROF_WARN("Unable to get hostname for filename pattern %s. Using " + "the default name.", + FilenamePat); return -1; } } else if (containsMergeSpecifier(FilenamePat, I)) { @@ -312,7 +336,8 @@ static int parseFilenamePattern(const char *FilenamePat) { } static void parseAndSetFilename(const char *FilenamePat, - ProfileNameSpecifier PNS) { + ProfileNameSpecifier PNS, + unsigned CopyFilenamePat) { const char *OldFilenamePat = lprofCurFilename.FilenamePat; ProfileNameSpecifier OldPNS = lprofCurFilename.PNS; @@ -323,33 +348,28 @@ static void parseAndSetFilename(const char *FilenamePat, if (!FilenamePat) FilenamePat = DefaultProfileName; - /* When -fprofile-instr-generate=<path> is specified on the - * command line, each module will be instrumented with runtime - * init call to __llvm_profile_init function which calls - * __llvm_profile_override_default_filename. In most of the cases, - * the path will be identical, so bypass the parsing completely. - */ if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) { lprofCurFilename.PNS = PNS; return; } /* When PNS >= OldPNS, the last one wins. */ - if (!FilenamePat || parseFilenamePattern(FilenamePat)) + if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat)) resetFilenameToDefault(); lprofCurFilename.PNS = PNS; if (!OldFilenamePat) { - PROF_NOTE("Set profile file path to \"%s\" via %s.\n", - lprofCurFilename.FilenamePat, getPNSStr(PNS)); + if (getenv("LLVM_PROFILE_VERBOSE")) + PROF_NOTE("Set profile file path to \"%s\" via %s.\n", + lprofCurFilename.FilenamePat, getPNSStr(PNS)); } else { - PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n", - OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat, - getPNSStr(PNS)); + if (getenv("LLVM_PROFILE_VERBOSE")) + PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n", + OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat, + getPNSStr(PNS)); } - if (!lprofCurFilename.MergePoolSize) - truncateCurrentFile(); + truncateCurrentFile(); } /* Return buffer length that is required to store the current profile @@ -429,16 +449,61 @@ static const char *getFilenamePatFromEnv(void) { return Filename; } +COMPILER_RT_VISIBILITY +const char *__llvm_profile_get_path_prefix(void) { + int Length; + char *FilenameBuf, *Prefix; + const char *Filename, *PrefixEnd; + + if (lprofCurFilename.ProfilePathPrefix) + return lprofCurFilename.ProfilePathPrefix; + + Length = getCurFilenameLength(); + FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); + Filename = getCurFilename(FilenameBuf); + if (!Filename) + return "\0"; + + PrefixEnd = lprofFindLastDirSeparator(Filename); + if (!PrefixEnd) + return "\0"; + + Length = PrefixEnd - Filename + 1; + Prefix = (char *)malloc(Length + 1); + if (!Prefix) { + PROF_ERR("Failed to %s\n", "allocate memory."); + return "\0"; + } + memcpy(Prefix, Filename, Length); + Prefix[Length] = '\0'; + lprofCurFilename.ProfilePathPrefix = Prefix; + return Prefix; +} + /* 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 * environment variable can override this default value. */ COMPILER_RT_VISIBILITY void __llvm_profile_initialize_file(void) { - const char *FilenamePat; + const char *EnvFilenamePat; + const char *SelectedPat = NULL; + ProfileNameSpecifier PNS = PNS_unknown; + int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0); + + EnvFilenamePat = getFilenamePatFromEnv(); + if (EnvFilenamePat) { + SelectedPat = EnvFilenamePat; + PNS = PNS_environment; + } else if (hasCommandLineOverrider) { + SelectedPat = INSTR_PROF_PROFILE_NAME_VAR; + PNS = PNS_command_line; + } else { + SelectedPat = NULL; + PNS = PNS_default; + } - FilenamePat = getFilenamePatFromEnv(); - parseAndSetFilename(FilenamePat, FilenamePat ? PNS_environment : PNS_default); + parseAndSetFilename(SelectedPat, PNS, 0); } /* This API is directly called by the user application code. It has the @@ -447,18 +512,7 @@ void __llvm_profile_initialize_file(void) { */ COMPILER_RT_VISIBILITY void __llvm_profile_set_filename(const char *FilenamePat) { - parseAndSetFilename(FilenamePat, PNS_runtime_api); -} - -/* - * This API is invoked by the global initializers emitted by Clang/LLVM when - * -fprofile-instr-generate=<..> is specified (vs -fprofile-instr-generate - * without an argument). This option has lower precedence than the - * LLVM_PROFILE_FILE environment variable. - */ -COMPILER_RT_VISIBILITY -void __llvm_profile_override_default_filename(const char *FilenamePat) { - parseAndSetFilename(FilenamePat, PNS_command_line); + parseAndSetFilename(FilenamePat, PNS_runtime_api, 1); } /* The public API for writing profile data into the file with name @@ -471,6 +525,12 @@ int __llvm_profile_write_file(void) { const char *Filename; char *FilenameBuf; + if (lprofProfileDumped()) { + PROF_NOTE("Profile data not written to file: %s.\n", + "already written"); + return 0; + } + Length = getCurFilenameLength(); FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); Filename = getCurFilename(FilenameBuf); @@ -497,6 +557,18 @@ int __llvm_profile_write_file(void) { return rc; } +COMPILER_RT_VISIBILITY +int __llvm_profile_dump(void) { + if (!doMerging()) + PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering " + " of previously dumped profile data : %s. Either use %%m " + "in profile name or change profile name before dumping.\n", + "online profile merging is not on"); + int rc = __llvm_profile_write_file(); + lprofSetProfileDumped(); + return rc; +} + static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); } COMPILER_RT_VISIBILITY diff --git a/lib/profile/InstrProfilingInternal.h b/lib/profile/InstrProfilingInternal.h index 44f308206ca8b..c73b291013023 100644 --- a/lib/profile/InstrProfilingInternal.h +++ b/lib/profile/InstrProfilingInternal.h @@ -163,21 +163,13 @@ void lprofSetupValueProfiler(); * to dump merged profile data into its own profile file. */ uint64_t lprofGetLoadModuleSignature(); -/* GCOV_PREFIX and GCOV_PREFIX_STRIP support */ -/* Return the path prefix specified by GCOV_PREFIX environment variable. - * If GCOV_PREFIX_STRIP is also specified, the strip level (integer value) - * is returned via \c *PrefixStrip. The prefix length is stored in *PrefixLen. +/* + * Return non zero value if the profile data has already been + * dumped to the file. */ -const char *lprofGetPathPrefix(int *PrefixStrip, size_t *PrefixLen); -/* Apply the path prefix specified in \c Prefix to path string in \c PathStr, - * and store the result to buffer pointed to by \c Buffer. If \c PrefixStrip - * is not zero, path prefixes are stripped from \c PathStr (the level of - * stripping is specified by \c PrefixStrip) before \c Prefix is added. - */ -void lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix, - size_t PrefixLen, int PrefixStrip); +unsigned lprofProfileDumped(); +void lprofSetProfileDumped(); -COMPILER_RT_VISIBILITY extern char *(*GetEnvHook)(const char *); COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *); COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer; COMPILER_RT_VISIBILITY extern uint32_t VPBufferSize; diff --git a/lib/profile/InstrProfilingPort.h b/lib/profile/InstrProfilingPort.h index c947153e25175..5789351956b94 100644 --- a/lib/profile/InstrProfilingPort.h +++ b/lib/profile/InstrProfilingPort.h @@ -40,14 +40,14 @@ #endif #define COMPILER_RT_MAX_HOSTLEN 128 -#ifdef _MSC_VER -#define COMPILER_RT_GETHOSTNAME(Name, Len) gethostname(Name, Len) -#elif defined(__ORBIS__) +#ifdef __ORBIS__ #define COMPILER_RT_GETHOSTNAME(Name, Len) ((void)(Name), (void)(Len), (-1)) #else #define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len) +#ifndef _MSC_VER #define COMPILER_RT_HAS_UNAME 1 #endif +#endif #if COMPILER_RT_HAS_ATOMICS == 1 #ifdef _MSC_VER diff --git a/lib/profile/InstrProfilingRuntime.cc b/lib/profile/InstrProfilingRuntime.cc index 12ad9f1573f4f..eb83074983ba3 100644 --- a/lib/profile/InstrProfilingRuntime.cc +++ b/lib/profile/InstrProfilingRuntime.cc @@ -11,7 +11,8 @@ extern "C" { #include "InstrProfiling.h" -COMPILER_RT_VISIBILITY int __llvm_profile_runtime; +/* int __llvm_profile_runtime */ +COMPILER_RT_VISIBILITY int INSTR_PROF_PROFILE_RUNTIME_VAR; } namespace { diff --git a/lib/profile/InstrProfilingUtil.c b/lib/profile/InstrProfilingUtil.c index 5c66933bc1af0..321c7192cc60f 100644 --- a/lib/profile/InstrProfilingUtil.c +++ b/lib/profile/InstrProfilingUtil.c @@ -35,7 +35,7 @@ void __llvm_profile_recursive_mkdir(char *path) { for (i = 1; path[i] != '\0'; ++i) { char save = path[i]; - if (!(path[i] == '/' || path[i] == '\\')) + if (!IS_DIR_SEPARATOR(path[i])) continue; path[i] = '\0'; #ifdef _WIN32 @@ -66,7 +66,19 @@ void *lprofPtrFetchAdd(void **Mem, long ByteIncr) { #endif -#ifdef COMPILER_RT_HAS_UNAME +#ifdef _MSC_VER +COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) { + WCHAR Buffer[COMPILER_RT_MAX_HOSTLEN]; + DWORD BufferSize = sizeof(Buffer); + BOOL Result = + GetComputerNameExW(ComputerNameDnsFullyQualified, Buffer, &BufferSize); + if (!Result) + return -1; + if (WideCharToMultiByte(CP_UTF8, 0, Buffer, -1, Name, Len, NULL, NULL) == 0) + return -1; + return 0; +} +#elif defined(COMPILER_RT_HAS_UNAME) COMPILER_RT_VISIBILITY int lprofGetHostName(char *Name, int Len) { struct utsname N; int R; @@ -184,3 +196,26 @@ lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix, memcpy(Dest + PrefixLen, StrippedPathStr, strlen(StrippedPathStr) + 1); } + +COMPILER_RT_VISIBILITY const char * +lprofFindFirstDirSeparator(const char *Path) { + const char *Sep; + Sep = strchr(Path, DIR_SEPARATOR); + if (Sep) + return Sep; +#if defined(DIR_SEPARATOR_2) + Sep = strchr(Path, DIR_SEPARATOR_2); +#endif + return Sep; +} + +COMPILER_RT_VISIBILITY const char *lprofFindLastDirSeparator(const char *Path) { + const char *Sep; + Sep = strrchr(Path, DIR_SEPARATOR); + if (Sep) + return Sep; +#if defined(DIR_SEPARATOR_2) + Sep = strrchr(Path, DIR_SEPARATOR_2); +#endif + return Sep; +} diff --git a/lib/profile/InstrProfilingUtil.h b/lib/profile/InstrProfilingUtil.h index 16d3fbf420f25..a80fde77e16a2 100644 --- a/lib/profile/InstrProfilingUtil.h +++ b/lib/profile/InstrProfilingUtil.h @@ -25,6 +25,27 @@ FILE *lprofOpenFileEx(const char *Filename); static inline char *getenv(const char *name) { return NULL; } #endif /* #if __ORBIS__ */ +/* GCOV_PREFIX and GCOV_PREFIX_STRIP support */ +/* Return the path prefix specified by GCOV_PREFIX environment variable. + * If GCOV_PREFIX_STRIP is also specified, the strip level (integer value) + * is returned via \c *PrefixStrip. The prefix length is stored in *PrefixLen. + */ +const char *lprofGetPathPrefix(int *PrefixStrip, size_t *PrefixLen); +/* Apply the path prefix specified in \c Prefix to path string in \c PathStr, + * and store the result to buffer pointed to by \c Buffer. If \c PrefixStrip + * is not zero, path prefixes are stripped from \c PathStr (the level of + * stripping is specified by \c PrefixStrip) before \c Prefix is added. + */ +void lprofApplyPathPrefix(char *Dest, const char *PathStr, const char *Prefix, + size_t PrefixLen, int PrefixStrip); + +/* Returns a pointer to the first occurrence of \c DIR_SEPARATOR char in + * the string \c Path, or NULL if the char is not found. */ +const char *lprofFindFirstDirSeparator(const char *Path); +/* Returns a pointer to the last occurrence of \c DIR_SEPARATOR char in + * the string \c Path, or NULL if the char is not found. */ +const char *lprofFindLastDirSeparator(const char *Path); + int lprofGetHostName(char *Name, int Len); unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV); diff --git a/lib/profile/InstrProfilingValue.c b/lib/profile/InstrProfilingValue.c index 93957e3237627..6648f8923584f 100644 --- a/lib/profile/InstrProfilingValue.c +++ b/lib/profile/InstrProfilingValue.c @@ -192,7 +192,7 @@ __llvm_profile_instrument_target(uint64_t TargetValue, void *Data, * the runtime can wipe out more than one lowest count entries * to give space for hot targets. */ - if (!(--MinCountVNode->Count)) { + if (!MinCountVNode->Count || !(--MinCountVNode->Count)) { CurVNode = MinCountVNode; CurVNode->Value = TargetValue; CurVNode->Count++; diff --git a/lib/profile/WindowsMMap.c b/lib/profile/WindowsMMap.c index 1f73420500325..f81d7da5389e6 100644 --- a/lib/profile/WindowsMMap.c +++ b/lib/profile/WindowsMMap.c @@ -20,6 +20,9 @@ #include "WindowsMMap.h" #include "InstrProfiling.h" +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + #ifdef __USE_FILE_OFFSET64 # define DWORD_HI(x) (x >> 32) # define DWORD_LO(x) ((x) & 0xffffffff) |