[compiler-rt] r364231 - (Reland with changes) Adding a function for setting coverage output file.
Sajjad Mirza via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 24 14:32:51 PDT 2019
Author: sajjadm
Date: Mon Jun 24 14:32:50 2019
New Revision: 364231
URL: http://llvm.org/viewvc/llvm-project?rev=364231&view=rev
Log:
(Reland with changes) Adding a function for setting coverage output file.
Summary:
User code can open a file on its own and pass it to the runtime, rather than
specifying a name and having the runtime open the file. This supports the use
case where a process cannot open a file on its own but can receive a file
descriptor from another process.
Relanding https://reviews.llvm.org/D62541. The original revision unlocked
the file before calling flush, this revision fixes that.
Reviewers: Dor1s, davidxl
Reviewed By: Dor1s
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D63581
Added:
compiler-rt/trunk/test/profile/instrprof-set-file-object-merging.c
compiler-rt/trunk/test/profile/instrprof-set-file-object.c
Modified:
compiler-rt/trunk/lib/profile/InstrProfiling.h
compiler-rt/trunk/lib/profile/InstrProfilingFile.c
compiler-rt/trunk/lib/profile/InstrProfilingUtil.c
compiler-rt/trunk/lib/profile/InstrProfilingUtil.h
Modified: compiler-rt/trunk/lib/profile/InstrProfiling.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfiling.h?rev=364231&r1=364230&r2=364231&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfiling.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfiling.h Mon Jun 24 14:32:50 2019
@@ -10,6 +10,7 @@
#define PROFILE_INSTRPROFILING_H_
#include "InstrProfilingPort.h"
+#include <stdio.h>
#define INSTR_PROF_VISIBILITY COMPILER_RT_VISIBILITY
#include "InstrProfData.inc"
@@ -125,7 +126,7 @@ int __llvm_orderfile_write_file(void);
/*!
* \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.
+ * 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
@@ -157,6 +158,24 @@ int __llvm_orderfile_dump(void);
*/
void __llvm_profile_set_filename(const char *Name);
+/*!
+ * \brief Set the FILE object for writing instrumentation data.
+ *
+ * Sets the FILE object to be used for subsequent calls to
+ * \a __llvm_profile_write_file(). The profile file name set by environment
+ * variable, command-line option, or calls to \a __llvm_profile_set_filename
+ * will be ignored.
+ *
+ * \c File will not be closed after a call to \a __llvm_profile_write_file() but
+ * it may be flushed. Passing NULL restores default behavior.
+ *
+ * If \c EnableMerge is nonzero, the runtime will always merge profiling data
+ * with the contents of the profiling file. If EnableMerge is zero, the runtime
+ * may still merge the data if it would have merged for another reason (for
+ * example, because of a %m specifier in the file name).
+ */
+void __llvm_profile_set_file_object(FILE *File, int EnableMerge);
+
/*! \brief Register to write instrumentation data to file at exit. */
int __llvm_profile_register_write_file_atexit(void);
Modified: compiler-rt/trunk/lib/profile/InstrProfilingFile.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingFile.c?rev=364231&r1=364230&r2=364231&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingFile.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingFile.c Mon Jun 24 14:32:50 2019
@@ -37,7 +37,7 @@
/* From where is profile name specified.
* The order the enumerators define their
* precedence. Re-order them may lead to
- * runtime behavior change. */
+ * runtime behavior change. */
typedef enum ProfileNameSpecifier {
PNS_unknown = 0,
PNS_default,
@@ -89,9 +89,27 @@ typedef struct lprofFilename {
COMPILER_RT_WEAK lprofFilename lprofCurFilename = {0, 0, 0, 0, {0},
{0}, 0, 0, 0, PNS_unknown};
+static int ProfileMergeRequested = 0;
+static int isProfileMergeRequested() { return ProfileMergeRequested; }
+static void setProfileMergeRequested(int EnableMerge) {
+ ProfileMergeRequested = EnableMerge;
+}
+
+static FILE *ProfileFile = NULL;
+static FILE *getProfileFile() { return ProfileFile; }
+static void setProfileFile(FILE *File) { ProfileFile = File; }
+
+COMPILER_RT_VISIBILITY void __llvm_profile_set_file_object(FILE *File,
+ int EnableMerge) {
+ setProfileFile(File);
+ setProfileMergeRequested(EnableMerge);
+}
+
static int getCurFilenameLength();
static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
-static unsigned doMerging() { return lprofCurFilename.MergePoolSize; }
+static unsigned doMerging() {
+ return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
+}
/* Return 1 if there is an error, otherwise return 0. */
static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
@@ -225,11 +243,16 @@ static void createProfileDir(const char
* its instrumented shared libraries dump profile data into their own data file.
*/
static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
- FILE *ProfileFile;
+ FILE *ProfileFile = NULL;
int rc;
- createProfileDir(ProfileFileName);
- ProfileFile = lprofOpenFileEx(ProfileFileName);
+ ProfileFile = getProfileFile();
+ if (ProfileFile) {
+ lprofLockFileHandle(ProfileFile);
+ } else {
+ createProfileDir(ProfileFileName);
+ ProfileFile = lprofOpenFileEx(ProfileFileName);
+ }
if (!ProfileFile)
return NULL;
@@ -244,6 +267,16 @@ static FILE *openFileForMerging(const ch
return ProfileFile;
}
+static FILE *getFileObject(const char *OutputName) {
+ FILE *File;
+ File = getProfileFile();
+ if (File != NULL) {
+ return File;
+ }
+
+ return fopen(OutputName, "ab");
+}
+
/* Write profile data to file \c OutputName. */
static int writeFile(const char *OutputName) {
int RetVal;
@@ -251,10 +284,10 @@ static int writeFile(const char *OutputN
int MergeDone = 0;
VPMergeHook = &lprofMergeValueProfData;
- if (!doMerging())
- OutputFile = fopen(OutputName, "ab");
- else
+ if (doMerging())
OutputFile = openFileForMerging(OutputName, &MergeDone);
+ else
+ OutputFile = getFileObject(OutputName);
if (!OutputFile)
return -1;
@@ -265,7 +298,15 @@ static int writeFile(const char *OutputN
initFileWriter(&fileWriter, OutputFile);
RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
- fclose(OutputFile);
+ if (OutputFile == getProfileFile()) {
+ fflush(OutputFile);
+ if (doMerging()) {
+ lprofUnlockFileHandle(OutputFile);
+ }
+ } else {
+ fclose(OutputFile);
+ }
+
return RetVal;
}
@@ -591,7 +632,7 @@ void __llvm_profile_initialize_file(void
EnvFilenamePat = getFilenamePatFromEnv();
if (EnvFilenamePat) {
- /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
+ /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
at the moment when __llvm_profile_write_file() gets executed. */
parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
return;
@@ -627,8 +668,7 @@ int __llvm_profile_write_file(void) {
int PDeathSig = 0;
if (lprofProfileDumped()) {
- PROF_NOTE("Profile data not written to file: %s.\n",
- "already written");
+ PROF_NOTE("Profile data not written to file: %s.\n", "already written");
return 0;
}
Modified: compiler-rt/trunk/lib/profile/InstrProfilingUtil.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingUtil.c?rev=364231&r1=364230&r2=364231&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingUtil.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingUtil.c Mon Jun 24 14:32:50 2019
@@ -154,6 +154,26 @@ COMPILER_RT_VISIBILITY int lprofUnlockFd
#endif
}
+COMPILER_RT_VISIBILITY int lprofLockFileHandle(FILE *F) {
+ int fd;
+#if defined(_WIN32)
+ fd = _fileno(F);
+#else
+ fd = fileno(F);
+#endif
+ return lprofLockFd(fd);
+}
+
+COMPILER_RT_VISIBILITY int lprofUnlockFileHandle(FILE *F) {
+ int fd;
+#if defined(_WIN32)
+ fd = _fileno(F);
+#else
+ fd = fileno(F);
+#endif
+ return lprofUnlockFd(fd);
+}
+
COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) {
FILE *f;
int fd;
Modified: compiler-rt/trunk/lib/profile/InstrProfilingUtil.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingUtil.h?rev=364231&r1=364230&r2=364231&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingUtil.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingUtil.h Mon Jun 24 14:32:50 2019
@@ -23,6 +23,8 @@ unsigned __llvm_profile_get_dir_mode(voi
int lprofLockFd(int fd);
int lprofUnlockFd(int fd);
+int lprofLockFileHandle(FILE *F);
+int lprofUnlockFileHandle(FILE *F);
/*! Open file \c Filename for read+write with write
* lock for exclusive access. The caller will block
Added: compiler-rt/trunk/test/profile/instrprof-set-file-object-merging.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/instrprof-set-file-object-merging.c?rev=364231&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/instrprof-set-file-object-merging.c (added)
+++ compiler-rt/trunk/test/profile/instrprof-set-file-object-merging.c Mon Jun 24 14:32:50 2019
@@ -0,0 +1,43 @@
+// Test that the specified output merges the profiling data.
+// Run the program twice so that the counters accumulate.
+// RUN: %clang -fprofile-instr-generate -fcoverage-mapping -o %t %s
+// RUN: %run %t %t.merging.profraw
+// RUN: %run %t %t.merging.profraw
+// RUN: test -f %t.merging.profraw
+// RUN: llvm-profdata merge -o %t.merging.profdata %t.merging.profraw
+// RUN: llvm-cov show -instr-profile %t.merging.profdata %t | FileCheck %s --match-full-lines
+// RUN: rm %t.merging.profdata %t.merging.profraw
+#include <stdio.h>
+
+extern void __llvm_profile_set_file_object(FILE *, int);
+
+int main(int argc, const char *argv[]) {
+ if (argc < 2)
+ return 1;
+
+ FILE *F = fopen(argv[1], "r+b");
+ if (!F) {
+ // File might not exist, try opening with truncation
+ F = fopen(argv[1], "w+b");
+ }
+ __llvm_profile_set_file_object(F, 1);
+
+ return 0;
+}
+// CHECK: 10| |#include <stdio.h>
+// CHECK: 11| |
+// CHECK: 12| |extern void __llvm_profile_set_file_object(FILE *, int);
+// CHECK: 13| |
+// CHECK: 14| 2|int main(int argc, const char *argv[]) {
+// CHECK: 15| 2| if (argc < 2)
+// CHECK: 16| 0| return 1;
+// CHECK: 17| 2|
+// CHECK: 18| 2| FILE *F = fopen(argv[1], "r+b");
+// CHECK: 19| 2| if (!F) {
+// CHECK: 20| 1| // File might not exist, try opening with truncation
+// CHECK: 21| 1| F = fopen(argv[1], "w+b");
+// CHECK: 22| 1| }
+// CHECK: 23| 2| __llvm_profile_set_file_object(F, 1);
+// CHECK: 24| 2|
+// CHECK: 25| 2| return 0;
+// CHECK: 26| 2|}
Added: compiler-rt/trunk/test/profile/instrprof-set-file-object.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/profile/instrprof-set-file-object.c?rev=364231&view=auto
==============================================================================
--- compiler-rt/trunk/test/profile/instrprof-set-file-object.c (added)
+++ compiler-rt/trunk/test/profile/instrprof-set-file-object.c Mon Jun 24 14:32:50 2019
@@ -0,0 +1,31 @@
+// Test that the specified output has profiling data.
+// RUN: %clang -fprofile-instr-generate -fcoverage-mapping -o %t %s
+// RUN: %run %t %t.file.profraw
+// RUN: test -f %t.file.profraw
+// RUN: llvm-profdata merge -o %t.file.profdata %t.file.profraw
+// RUN: llvm-cov show -instr-profile %t.file.profdata %t | FileCheck %s --match-full-lines
+// RUN: rm %t.file.profraw %t.file.profdata
+#include <stdio.h>
+
+extern void __llvm_profile_set_file_object(FILE *, int);
+
+int main(int argc, const char *argv[]) {
+ if (argc < 2)
+ return 1;
+
+ FILE *F = fopen(argv[1], "w+b");
+ __llvm_profile_set_file_object(F, 0);
+ return 0;
+}
+// CHECK: 8| |#include <stdio.h>
+// CHECK: 9| |
+// CHECK: 10| |extern void __llvm_profile_set_file_object(FILE *, int);
+// CHECK: 11| |
+// CHECK: 12| 1|int main(int argc, const char *argv[]) {
+// CHECK: 13| 1| if (argc < 2)
+// CHECK: 14| 0| return 1;
+// CHECK: 15| 1|
+// CHECK: 16| 1| FILE *F = fopen(argv[1], "w+b");
+// CHECK: 17| 1| __llvm_profile_set_file_object(F, 0);
+// CHECK: 18| 1| return 0;
+// CHECK: 19| 1|}
More information about the llvm-commits
mailing list