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"
@@ -1828,7 +1829,8 @@ static StringRef getOutputFilename(Compilation &C,
1828
1829
1829
1830
static void addAuxiliaryOutput (Compilation &C, CommandOutput &output,
1830
1831
types::ID outputType, const OutputInfo &OI,
1831
- const TypeToPathMap *outputMap) {
1832
+ const TypeToPathMap *outputMap,
1833
+ StringRef outputPath = StringRef()) {
1832
1834
StringRef outputMapPath;
1833
1835
if (outputMap) {
1834
1836
auto iter = outputMap->find (outputType);
@@ -1839,6 +1841,8 @@ static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
1839
1841
if (!outputMapPath.empty ()) {
1840
1842
// Prefer a path from the OutputMap.
1841
1843
output.setAdditionalOutputForType (outputType, outputMapPath);
1844
+ } else if (!outputPath.empty ()) {
1845
+ output.setAdditionalOutputForType (outputType, outputPath);
1842
1846
} else {
1843
1847
// Put the auxiliary output file next to the primary output file.
1844
1848
llvm::SmallString<128 > path;
@@ -1858,6 +1862,58 @@ static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
1858
1862
}
1859
1863
}
1860
1864
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
+
1861
1917
// / If the file at \p input has not been modified since the last build (i.e. its
1862
1918
// / mtime has not changed), adjust the Job's condition accordingly.
1863
1919
static void
@@ -2092,8 +2148,14 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
2092
2148
if (isa<CompileJobAction>(JA) || isa<GeneratePCHJobAction>(JA)) {
2093
2149
// Choose the serialized diagnostics output path.
2094
2150
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
+ }
2097
2159
2098
2160
// Remove any existing diagnostics files so that clients can detect their
2099
2161
// presence to determine if a command was run.
0 commit comments