Skip to content

Commit ef98f92

Browse files
committed
[driver] For the persistent bridging PCH job action, make sure to pass a serialized diagnostics path in the PCH output directory
Previously it was passing a relative filename and the invocation was creating .dia files in the source directory. If a filename is not determined for inside the PCH output directory, it fallsback to creating a temporary for the diagnostics file, similarly to the non-persistent bridging PCH job. rdar://32594291
1 parent 1d407a1 commit ef98f92

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

lib/Driver/Driver.cpp

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "swift/Option/SanitizerOptions.h"
3636
#include "swift/Parse/Lexer.h"
3737
#include "swift/Config.h"
38+
#include "llvm/ADT/APInt.h"
3839
#include "llvm/ADT/DenseSet.h"
3940
#include "llvm/ADT/STLExtras.h"
4041
#include "llvm/ADT/SmallString.h"
@@ -1828,7 +1829,8 @@ static StringRef getOutputFilename(Compilation &C,
18281829

18291830
static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
18301831
types::ID outputType, const OutputInfo &OI,
1831-
const TypeToPathMap *outputMap) {
1832+
const TypeToPathMap *outputMap,
1833+
StringRef outputPath = StringRef()) {
18321834
StringRef outputMapPath;
18331835
if (outputMap) {
18341836
auto iter = outputMap->find(outputType);
@@ -1839,6 +1841,8 @@ static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
18391841
if (!outputMapPath.empty()) {
18401842
// Prefer a path from the OutputMap.
18411843
output.setAdditionalOutputForType(outputType, outputMapPath);
1844+
} else if (!outputPath.empty()) {
1845+
output.setAdditionalOutputForType(outputType, outputPath);
18421846
} else {
18431847
// Put the auxiliary output file next to the primary output file.
18441848
llvm::SmallString<128> path;
@@ -1858,6 +1862,58 @@ static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
18581862
}
18591863
}
18601864

1865+
static void addDiagFileOutputForPersistentPCHAction(Compilation &C,
1866+
const GeneratePCHJobAction *JA,
1867+
CommandOutput &output,
1868+
const OutputInfo &OI,
1869+
const TypeToPathMap *outputMap,
1870+
DiagnosticEngine &diags) {
1871+
assert(JA->isPersistentPCH());
1872+
1873+
// For a persistent PCH we don't use an output, the frontend determines
1874+
// the filename to use for the PCH. For the diagnostics file, try to
1875+
// determine an invocation-specific path inside the directory where the
1876+
// PCH is going to be written, and fallback to a temporary file if we
1877+
// cannot determine such a path.
1878+
1879+
StringRef pchOutDir = JA->getPersistentPCHDir();
1880+
StringRef headerPath = output.getBaseInput(JA->getInputIndex());
1881+
StringRef stem = llvm::sys::path::stem(headerPath);
1882+
StringRef suffix = types::getTypeTempSuffix(types::TY_SerializedDiagnostics);
1883+
SmallString<256> outPathBuf;
1884+
1885+
if (const Arg *A = C.getArgs().getLastArg(options::OPT_emit_module_path)) {
1886+
// The module file path is unique for a specific module and architecture
1887+
// (it won't be concurrently written to) so we can use the path as hash
1888+
// for determining the filename to use for the diagnostic file.
1889+
StringRef ModuleOutPath = A->getValue();
1890+
outPathBuf = pchOutDir;
1891+
llvm::sys::path::append(outPathBuf, stem);
1892+
outPathBuf += '-';
1893+
auto code = llvm::hash_value(ModuleOutPath);
1894+
outPathBuf += llvm::APInt(64, code).toString(36, /*Signed=*/false);
1895+
llvm::sys::path::replace_extension(outPathBuf, suffix);
1896+
}
1897+
1898+
if (outPathBuf.empty()) {
1899+
// Fallback to creating a temporary file.
1900+
std::error_code EC =
1901+
llvm::sys::fs::createTemporaryFile(stem, suffix, outPathBuf);
1902+
if (EC) {
1903+
diags.diagnose(SourceLoc(),
1904+
diag::error_unable_to_make_temporary_file,
1905+
EC.message());
1906+
return;
1907+
}
1908+
C.addTemporaryFile(outPathBuf.str());
1909+
}
1910+
1911+
if (!outPathBuf.empty()) {
1912+
addAuxiliaryOutput(C, output, types::TY_SerializedDiagnostics, OI,
1913+
outputMap, outPathBuf.str());
1914+
}
1915+
}
1916+
18611917
/// If the file at \p input has not been modified since the last build (i.e. its
18621918
/// mtime has not changed), adjust the Job's condition accordingly.
18631919
static void
@@ -2092,8 +2148,14 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
20922148
if (isa<CompileJobAction>(JA) || isa<GeneratePCHJobAction>(JA)) {
20932149
// Choose the serialized diagnostics output path.
20942150
if (C.getArgs().hasArg(options::OPT_serialize_diagnostics)) {
2095-
addAuxiliaryOutput(C, *Output, types::TY_SerializedDiagnostics, OI,
2096-
OutputMap);
2151+
auto pchJA = dyn_cast<GeneratePCHJobAction>(JA);
2152+
if (pchJA && pchJA->isPersistentPCH()) {
2153+
addDiagFileOutputForPersistentPCHAction(C, pchJA, *Output, OI,
2154+
OutputMap, Diags);
2155+
} else {
2156+
addAuxiliaryOutput(C, *Output, types::TY_SerializedDiagnostics, OI,
2157+
OutputMap);
2158+
}
20972159

20982160
// Remove any existing diagnostics files so that clients can detect their
20992161
// presence to determine if a command was run.

test/Driver/bridging-pch.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
// PERSISTENT-YESPCHJOB: {{.*}}swift -frontend {{.*}} -emit-pch -pch-output-dir {{.*}}/pch
3737
// PERSISTENT-YESPCHJOB: {{.*}}swift -frontend {{.*}} -import-objc-header {{.*}}bridging-header.h -pch-output-dir {{.*}}/pch -pch-disable-validation
3838

39+
// RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -serialize-diagnostics %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHJOB-DIAG1
40+
// PERSISTENT-YESPCHJOB-DIAG1: {{.*}}swift -frontend {{.*}} -serialize-diagnostics-path {{.*}}bridging-header-{{.*}}.dia {{.*}} -emit-pch -pch-output-dir {{.*}}/pch
41+
42+
// RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch-out-dir -serialize-diagnostics %s -emit-module -emit-module-path /module-path-dir 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHJOB-DIAG2
43+
// PERSISTENT-YESPCHJOB-DIAG2: {{.*}}swift -frontend {{.*}} -serialize-diagnostics-path {{.*}}/pch-out-dir/bridging-header-{{.*}}.dia {{.*}} -emit-pch -pch-output-dir {{.*}}/pch-out-dir
44+
3945
// RUN: %swiftc_driver -typecheck -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -parseable-output -driver-skip-execution %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-OUTPUT
4046
// PERSISTENT-OUTPUT-NOT: "outputs": [
4147

0 commit comments

Comments
 (0)