Skip to content

Commit 9b4eb32

Browse files
committed
[profile] Add %t LLVM_PROFILE_FILE option to substitute $TMPDIR
Add support for expanding the %t filename specifier in LLVM_PROFILE_FILE to the TMPDIR environment variable. This is supported on all platforms. On Darwin, TMPDIR is used to specify a temporary application-specific scratch directory. When testing apps on remote devices, it can be challenging for the host device to determine the correct TMPDIR, so it's helpful to have the runtime do this work. rdar://68524185 Differential Revision: https://reviews.llvm.org/D87332 (cherry picked from commit 62c3727)
1 parent 7876079 commit 9b4eb32

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

clang/docs/SourceBasedCodeCoverage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ directory structure will be created. Additionally, the following special
7979

8080
* "%h" expands out to the hostname of the machine running the program.
8181

82+
* "%t" expands out to the value of the ``TMPDIR`` environment variable. On
83+
Darwin, this is typically set to a temporary scratch directory.
84+
8285
* "%Nm" expands out to the instrumented binary's signature. When this pattern
8386
is specified, the runtime creates a pool of N raw profiles which are used for
8487
on-line profile merging. The runtime takes care of selecting a raw profile

compiler-rt/lib/profile/InstrProfilingFile.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ typedef struct lprofFilename {
7474
unsigned OwnsFilenamePat;
7575
const char *ProfilePathPrefix;
7676
char PidChars[MAX_PID_SIZE];
77+
char *TmpDir;
7778
char Hostname[COMPILER_RT_MAX_HOSTLEN];
7879
unsigned NumPids;
7980
unsigned NumHosts;
@@ -90,8 +91,8 @@ typedef struct lprofFilename {
9091
ProfileNameSpecifier PNS;
9192
} lprofFilename;
9293

93-
static lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0}, 0,
94-
0, 0, {0}, 0, PNS_unknown};
94+
static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL, {0},
95+
0, 0, 0, {0}, 0, PNS_unknown};
9596

9697
static int ProfileMergeRequested = 0;
9798
static int isProfileMergeRequested() { return ProfileMergeRequested; }
@@ -773,6 +774,14 @@ static int parseFilenamePattern(const char *FilenamePat,
773774
FilenamePat);
774775
return -1;
775776
}
777+
} else if (FilenamePat[I] == 't') {
778+
lprofCurFilename.TmpDir = getenv("TMPDIR");
779+
if (!lprofCurFilename.TmpDir) {
780+
PROF_WARN("Unable to get the TMPDIR environment variable, referenced "
781+
"in %s. Using the default path.",
782+
FilenamePat);
783+
return -1;
784+
}
776785
} else if (FilenamePat[I] == 'c') {
777786
if (__llvm_profile_is_continuous_mode_enabled()) {
778787
PROF_WARN("%%c specifier can only be specified once in %s.\n",
@@ -874,12 +883,14 @@ static int getCurFilenameLength() {
874883
return 0;
875884

876885
if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
877-
lprofCurFilename.MergePoolSize || lprofCurFilename.NumExitSignals))
886+
lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
887+
lprofCurFilename.NumExitSignals))
878888
return strlen(lprofCurFilename.FilenamePat);
879889

880890
Len = strlen(lprofCurFilename.FilenamePat) +
881891
lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
882-
lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
892+
lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) +
893+
(lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0);
883894
if (lprofCurFilename.MergePoolSize)
884895
Len += SIGLEN;
885896
for (I = 0; I < lprofCurFilename.NumExitSignals; ++I) {
@@ -896,14 +907,14 @@ static int getCurFilenameLength() {
896907
* current filename pattern string is directly returned, unless ForceUseBuf
897908
* is enabled. */
898909
static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
899-
int I, J, PidLength, HostNameLength, FilenamePatLength;
910+
int I, J, PidLength, HostNameLength, TmpDirLength, FilenamePatLength;
900911
const char *FilenamePat = lprofCurFilename.FilenamePat;
901912

902913
if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
903914
return 0;
904915

905916
if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
906-
lprofCurFilename.MergePoolSize ||
917+
lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
907918
__llvm_profile_is_continuous_mode_enabled() ||
908919
lprofCurFilename.NumExitSignals)) {
909920
if (!ForceUseBuf)
@@ -917,6 +928,7 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
917928

918929
PidLength = strlen(lprofCurFilename.PidChars);
919930
HostNameLength = strlen(lprofCurFilename.Hostname);
931+
TmpDirLength = lprofCurFilename.TmpDir ? strlen(lprofCurFilename.TmpDir) : 0;
920932
/* Construct the new filename. */
921933
for (I = 0, J = 0; FilenamePat[I]; ++I)
922934
if (FilenamePat[I] == '%') {
@@ -929,6 +941,10 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
929941
} else if (containsExitOnSignalSpecifier(FilenamePat, I)) {
930942
while (FilenamePat[I] != 'x')
931943
++I;
944+
} else if (FilenamePat[I] == 't') {
945+
memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength);
946+
FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR;
947+
J += TmpDirLength + 1;
932948
} else {
933949
if (!getMergePoolSize(FilenamePat, &I))
934950
continue;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: cd %t
4+
// RUN: %clang_profgen -o %t/binary %s
5+
//
6+
// Check that a dir separator is appended after %t is subsituted.
7+
// RUN: env TMPDIR="%t" LLVM_PROFILE_FILE="%%traw1.profraw" %run ./binary
8+
// RUN: llvm-profdata show ./raw1.profraw | FileCheck %s -check-prefix TMPDIR
9+
//
10+
// Check that substitution works even if a redundant dir separator is added.
11+
// RUN: env TMPDIR="%t" LLVM_PROFILE_FILE="%%t/raw2.profraw" %run ./binary
12+
// RUN: llvm-profdata show ./raw2.profraw | FileCheck %s -check-prefix TMPDIR
13+
//
14+
// Check that we fall back to the default path if TMPDIR is missing.
15+
// RUN: env -u TMPDIR LLVM_PROFILE_FILE="%%t/raw3.profraw" %run ./binary 2>&1 | FileCheck %s -check-prefix MISSING
16+
// RUN: llvm-profdata show ./default.profraw | FileCheck %s -check-prefix TMPDIR
17+
18+
// TMPDIR: Maximum function count: 1
19+
20+
// MISSING: Unable to get the TMPDIR environment variable, referenced in {{.*}}raw3.profraw. Using the default path.
21+
22+
int main() { return 0; }

0 commit comments

Comments
 (0)