@@ -133,6 +133,134 @@ createSwiftCachingOutputBackend(
133
133
InputsAndOutputs);
134
134
}
135
135
136
+ bool replayCachedCompilerOutputs (
137
+ ObjectStore &CAS, ActionCache &Cache, ObjectRef BaseKey,
138
+ DiagnosticEngine &Diag, const FrontendInputsAndOutputs &InputsAndOutputs,
139
+ CachingDiagnosticsProcessor &CDP) {
140
+ clang::cas::CompileJobResultSchema Schema (CAS);
141
+ bool CanReplayAllOutput = true ;
142
+ struct OutputEntry {
143
+ std::string Path;
144
+ std::string Key;
145
+ llvm::cas::ObjectProxy Proxy;
146
+ };
147
+ SmallVector<OutputEntry> OutputProxies;
148
+
149
+ auto replayOutputFile = [&](StringRef InputName, file_types::ID OutputKind,
150
+ StringRef OutputPath) -> Optional<OutputEntry> {
151
+ LLVM_DEBUG (llvm::dbgs ()
152
+ << " DEBUG: lookup output \' " << OutputPath << " \' type \' "
153
+ << file_types::getTypeName (OutputKind) << " \' input \' "
154
+ << InputName << " \n " ;);
155
+
156
+ auto OutputKey =
157
+ createCompileJobCacheKeyForOutput (CAS, BaseKey, InputName, OutputKind);
158
+ if (!OutputKey) {
159
+ Diag.diagnose (SourceLoc (), diag::error_cas,
160
+ toString (OutputKey.takeError ()));
161
+ return None;
162
+ }
163
+ auto OutputKeyID = CAS.getID (*OutputKey);
164
+ auto Lookup = Cache.get (OutputKeyID);
165
+ if (!Lookup) {
166
+ Diag.diagnose (SourceLoc (), diag::error_cas, toString (Lookup.takeError ()));
167
+ return None;
168
+ }
169
+ if (!*Lookup) {
170
+ Diag.diagnose (SourceLoc (), diag::output_cache_miss, OutputPath,
171
+ OutputKeyID.toString ());
172
+ return None;
173
+ }
174
+ auto OutputRef = CAS.getReference (**Lookup);
175
+ if (!OutputRef) {
176
+ return None;
177
+ }
178
+ auto Result = Schema.load (*OutputRef);
179
+ if (!Result) {
180
+ Diag.diagnose (SourceLoc (), diag::error_cas, toString (Result.takeError ()));
181
+ return None;
182
+ }
183
+ auto MainOutput = Result->getOutput (
184
+ clang::cas::CompileJobCacheResult::OutputKind::MainOutput);
185
+ if (!MainOutput) {
186
+ return None;
187
+ }
188
+ auto LoadedResult = CAS.getProxy (MainOutput->Object );
189
+ if (!LoadedResult) {
190
+ Diag.diagnose (SourceLoc (), diag::error_cas,
191
+ toString (LoadedResult.takeError ()));
192
+ return None;
193
+ }
194
+
195
+ return OutputEntry{OutputPath.str (), OutputKeyID.toString (), *LoadedResult};
196
+ };
197
+
198
+ auto replayOutputFromInput = [&](const InputFile &Input) {
199
+ auto InputPath = Input.getFileName ();
200
+ if (!Input.outputFilename ().empty ()) {
201
+ if (auto Result = replayOutputFile (
202
+ InputPath, InputsAndOutputs.getPrincipalOutputType (),
203
+ Input.outputFilename ()))
204
+ OutputProxies.emplace_back (*Result);
205
+ else
206
+ CanReplayAllOutput = false ;
207
+ }
208
+
209
+ Input.getPrimarySpecificPaths ()
210
+ .SupplementaryOutputs .forEachSetOutputAndType (
211
+ [&](const std::string &File, file_types::ID ID) {
212
+ if (ID == file_types::ID::TY_SerializedDiagnostics)
213
+ return ;
214
+
215
+ if (auto Result = replayOutputFile (InputPath, ID, File))
216
+ OutputProxies.emplace_back (*Result);
217
+ else
218
+ CanReplayAllOutput = false ;
219
+ });
220
+ };
221
+
222
+ llvm::for_each (InputsAndOutputs.getAllInputs (), replayOutputFromInput);
223
+
224
+ auto DiagnosticsOutput = replayOutputFile (
225
+ " <cached-diagnostics>" , file_types::ID::TY_CachedDiagnostics,
226
+ " <cached-diagnostics>" );
227
+ if (!DiagnosticsOutput)
228
+ CanReplayAllOutput = false ;
229
+
230
+ if (!CanReplayAllOutput)
231
+ return false ;
232
+
233
+ // Replay Diagnostics first so the output failures comes after.
234
+ // Also if the diagnostics replay failed, proceed to re-compile.
235
+ if (auto E = CDP.replayCachedDiagnostics (
236
+ DiagnosticsOutput->Proxy .getData ())) {
237
+ Diag.diagnose (SourceLoc (), diag::error_replay_cached_diag,
238
+ toString (std::move (E)));
239
+ return false ;
240
+ }
241
+
242
+ // Replay the result only when everything is resolved.
243
+ // Use on disk output backend directly here to write to disk.
244
+ llvm::vfs::OnDiskOutputBackend Backend;
245
+ for (auto &Output : OutputProxies) {
246
+ auto File = Backend.createFile (Output.Path );
247
+ if (!File) {
248
+ Diag.diagnose (SourceLoc (), diag::error_opening_output, Output.Path ,
249
+ toString (File.takeError ()));
250
+ continue ;
251
+ }
252
+ *File << Output.Proxy .getData ();
253
+ if (auto E = File->keep ()) {
254
+ Diag.diagnose (SourceLoc (), diag::error_closing_output, Output.Path ,
255
+ toString (std::move (E)));
256
+ continue ;
257
+ }
258
+ Diag.diagnose (SourceLoc (), diag::replay_output, Output.Path , Output.Key );
259
+ }
260
+
261
+ return true ;
262
+ }
263
+
136
264
static Expected<std::unique_ptr<llvm::MemoryBuffer>>
137
265
loadCachedCompileResultFromCacheKeyImpl (ObjectStore &CAS, ActionCache &Cache,
138
266
StringRef CacheKey,
0 commit comments