35
35
#include " swift/Option/SanitizerOptions.h"
36
36
#include " swift/Parse/Lexer.h"
37
37
#include " swift/Config.h"
38
+ #include " llvm/ADT/APInt.h"
38
39
#include " llvm/ADT/DenseSet.h"
39
40
#include " llvm/ADT/STLExtras.h"
40
41
#include " llvm/ADT/SmallString.h"
@@ -1844,7 +1845,8 @@ static StringRef getOutputFilename(Compilation &C,
1844
1845
1845
1846
static void addAuxiliaryOutput (Compilation &C, CommandOutput &output,
1846
1847
types::ID outputType, const OutputInfo &OI,
1847
- const TypeToPathMap *outputMap) {
1848
+ const TypeToPathMap *outputMap,
1849
+ StringRef outputPath = StringRef()) {
1848
1850
StringRef outputMapPath;
1849
1851
if (outputMap) {
1850
1852
auto iter = outputMap->find (outputType);
@@ -1855,6 +1857,8 @@ static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
1855
1857
if (!outputMapPath.empty ()) {
1856
1858
// Prefer a path from the OutputMap.
1857
1859
output.setAdditionalOutputForType (outputType, outputMapPath);
1860
+ } else if (!outputPath.empty ()) {
1861
+ output.setAdditionalOutputForType (outputType, outputPath);
1858
1862
} else {
1859
1863
// Put the auxiliary output file next to the primary output file.
1860
1864
llvm::SmallString<128 > path;
@@ -1874,6 +1878,58 @@ static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
1874
1878
}
1875
1879
}
1876
1880
1881
+ static void addDiagFileOutputForPersistentPCHAction (Compilation &C,
1882
+ const GeneratePCHJobAction *JA,
1883
+ CommandOutput &output,
1884
+ const OutputInfo &OI,
1885
+ const TypeToPathMap *outputMap,
1886
+ DiagnosticEngine &diags) {
1887
+ assert (JA->isPersistentPCH ());
1888
+
1889
+ // For a persistent PCH we don't use an output, the frontend determines
1890
+ // the filename to use for the PCH. For the diagnostics file, try to
1891
+ // determine an invocation-specific path inside the directory where the
1892
+ // PCH is going to be written, and fallback to a temporary file if we
1893
+ // cannot determine such a path.
1894
+
1895
+ StringRef pchOutDir = JA->getPersistentPCHDir ();
1896
+ StringRef headerPath = output.getBaseInput (JA->getInputIndex ());
1897
+ StringRef stem = llvm::sys::path::stem (headerPath);
1898
+ StringRef suffix = types::getTypeTempSuffix (types::TY_SerializedDiagnostics);
1899
+ SmallString<256 > outPathBuf;
1900
+
1901
+ if (const Arg *A = C.getArgs ().getLastArg (options::OPT_emit_module_path)) {
1902
+ // The module file path is unique for a specific module and architecture
1903
+ // (it won't be concurrently written to) so we can use the path as hash
1904
+ // for determining the filename to use for the diagnostic file.
1905
+ StringRef ModuleOutPath = A->getValue ();
1906
+ outPathBuf = pchOutDir;
1907
+ llvm::sys::path::append (outPathBuf, stem);
1908
+ outPathBuf += ' -' ;
1909
+ auto code = llvm::hash_value (ModuleOutPath);
1910
+ outPathBuf += llvm::APInt (64 , code).toString (36 , /* Signed=*/ false );
1911
+ llvm::sys::path::replace_extension (outPathBuf, suffix);
1912
+ }
1913
+
1914
+ if (outPathBuf.empty ()) {
1915
+ // Fallback to creating a temporary file.
1916
+ std::error_code EC =
1917
+ llvm::sys::fs::createTemporaryFile (stem, suffix, outPathBuf);
1918
+ if (EC) {
1919
+ diags.diagnose (SourceLoc (),
1920
+ diag::error_unable_to_make_temporary_file,
1921
+ EC.message ());
1922
+ return ;
1923
+ }
1924
+ C.addTemporaryFile (outPathBuf.str ());
1925
+ }
1926
+
1927
+ if (!outPathBuf.empty ()) {
1928
+ addAuxiliaryOutput (C, output, types::TY_SerializedDiagnostics, OI,
1929
+ outputMap, outPathBuf.str ());
1930
+ }
1931
+ }
1932
+
1877
1933
// / If the file at \p input has not been modified since the last build (i.e. its
1878
1934
// / mtime has not changed), adjust the Job's condition accordingly.
1879
1935
static void
@@ -2108,8 +2164,14 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
2108
2164
if (isa<CompileJobAction>(JA) || isa<GeneratePCHJobAction>(JA)) {
2109
2165
// Choose the serialized diagnostics output path.
2110
2166
if (C.getArgs ().hasArg (options::OPT_serialize_diagnostics)) {
2111
- addAuxiliaryOutput (C, *Output, types::TY_SerializedDiagnostics, OI,
2112
- OutputMap);
2167
+ auto pchJA = dyn_cast<GeneratePCHJobAction>(JA);
2168
+ if (pchJA && pchJA->isPersistentPCH ()) {
2169
+ addDiagFileOutputForPersistentPCHAction (C, pchJA, *Output, OI,
2170
+ OutputMap, Diags);
2171
+ } else {
2172
+ addAuxiliaryOutput (C, *Output, types::TY_SerializedDiagnostics, OI,
2173
+ OutputMap);
2174
+ }
2113
2175
2114
2176
// Remove any existing diagnostics files so that clients can detect their
2115
2177
// presence to determine if a command was run.
0 commit comments