@@ -42,7 +42,8 @@ enum class SwiftCacheToolAction {
4242 Invalid,
4343 PrintBaseKey,
4444 PrintOutputKeys,
45- ValidateOutputs
45+ ValidateOutputs,
46+ RenderDiags
4647};
4748
4849struct OutputEntry {
@@ -134,11 +135,13 @@ class SwiftCacheToolInvocation {
134135 .Case (" print-base-key" , SwiftCacheToolAction::PrintBaseKey)
135136 .Case (" print-output-keys" , SwiftCacheToolAction::PrintOutputKeys)
136137 .Case (" validate-outputs" , SwiftCacheToolAction::ValidateOutputs)
138+ .Case (" render-diags" , SwiftCacheToolAction::RenderDiags)
137139 .Default (SwiftCacheToolAction::Invalid);
138140
139141 if (ActionKind == SwiftCacheToolAction::Invalid) {
140- llvm::errs () << " Invalid option specified for -cache-tool-action: "
141- << " use print-base-key|print-output-keys|validate-outputs\n " ;
142+ llvm::errs ()
143+ << " Invalid option specified for -cache-tool-action: "
144+ << " print-base-key|print-output-keys|validate-outputs|render-diags\n " ;
142145 return 1 ;
143146 }
144147
@@ -153,6 +156,8 @@ class SwiftCacheToolInvocation {
153156 return printOutputKeys ();
154157 case SwiftCacheToolAction::ValidateOutputs:
155158 return validateOutputs ();
159+ case SwiftCacheToolAction::RenderDiags:
160+ return renderDiags ();
156161 case SwiftCacheToolAction::Invalid:
157162 return 0 ; // No action. Probably just print help. Return.
158163 }
@@ -202,6 +207,10 @@ class SwiftCacheToolInvocation {
202207 return true ;
203208 }
204209
210+ // Disable diagnostic caching from this fake instance.
211+ if (auto *CDP = Instance.getCachingDiagnosticsProcessor ())
212+ CDP->endDiagnosticCapture ();
213+
205214 return false ;
206215 }
207216
@@ -233,6 +242,7 @@ class SwiftCacheToolInvocation {
233242
234243 int printOutputKeys ();
235244 int validateOutputs ();
245+ int renderDiags ();
236246};
237247
238248} // end anonymous namespace
@@ -283,6 +293,10 @@ int SwiftCacheToolInvocation::printOutputKeys() {
283293 Invocation.getFrontendOptions ().InputsAndOutputs .getAllInputs (),
284294 addFromInputFile);
285295
296+ // Add diagnostics file.
297+ addOutputKey (" <cached-diagnostics>" , file_types::ID::TY_CachedDiagnostics,
298+ " <cached-diagnostics>" );
299+
286300 if (hasError)
287301 return 1 ;
288302
@@ -301,6 +315,26 @@ int SwiftCacheToolInvocation::printOutputKeys() {
301315 return 0 ;
302316}
303317
318+ static llvm::Expected<llvm::json::Array>
319+ readOutputEntriesFromFile (StringRef Path) {
320+ auto JSONContent = llvm::MemoryBuffer::getFile (Path);
321+ if (!JSONContent)
322+ return llvm::createStringError (JSONContent.getError (),
323+ " failed to read input file" );
324+
325+ auto JSONValue = llvm::json::parse ((*JSONContent)->getBuffer ());
326+ if (!JSONValue)
327+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
328+ " failed to parse input file as JSON" );
329+
330+ auto Keys = JSONValue->getAsArray ();
331+ if (!Keys)
332+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
333+ " invalid JSON format for input file" );
334+
335+ return *Keys;
336+ }
337+
304338int SwiftCacheToolInvocation::validateOutputs () {
305339 auto DB = llvm::cas::createOnDiskUnifiedCASDatabases (CASPath);
306340 if (!DB)
@@ -310,22 +344,10 @@ int SwiftCacheToolInvocation::validateOutputs() {
310344 Instance.getDiags ().addConsumer (PDC);
311345
312346 auto validateCacheKeysFromFile = [&](const std::string &Path) {
313- auto JSONContent = llvm::MemoryBuffer::getFile (Path);
314- if (!JSONContent) {
315- llvm::errs () << " failed to read " << Path << " : "
316- << JSONContent.getError ().message () << " \n " ;
317- return true ;
318- }
319- auto JSONValue = llvm::json::parse ((*JSONContent)->getBuffer ());
320- if (!JSONValue) {
321- llvm::errs () << " failed to parse " << Path << " : "
322- << toString (JSONValue.takeError ()) << " \n " ;
323- return true ;
324- }
325-
326- auto Keys = JSONValue->getAsArray ();
347+ auto Keys = readOutputEntriesFromFile (Path);
327348 if (!Keys) {
328- llvm::errs () << " invalid keys format in " << Path << " \n " ;
349+ llvm::errs () << " cannot read file " << Path << " : "
350+ << toString (Keys.takeError ()) << " \n " ;
329351 return true ;
330352 }
331353
@@ -350,6 +372,51 @@ int SwiftCacheToolInvocation::validateOutputs() {
350372 return llvm::any_of (Inputs, validateCacheKeysFromFile);
351373}
352374
375+ int SwiftCacheToolInvocation::renderDiags () {
376+ if (setupCompiler ())
377+ return 1 ;
378+
379+ auto *CDP = Instance.getCachingDiagnosticsProcessor ();
380+ if (!CDP) {
381+ llvm::errs () << " provided commandline doesn't support cached diagnostics\n " ;
382+ return 1 ;
383+ }
384+
385+ auto renderDiagsFromFile = [&](const std::string &Path) {
386+ auto Keys = readOutputEntriesFromFile (Path);
387+ if (!Keys) {
388+ llvm::errs () << " cannot read file " << Path << " : "
389+ << toString (Keys.takeError ()) << " \n " ;
390+ return true ;
391+ }
392+
393+ for (const auto & Entry : *Keys) {
394+ if (auto *Obj = Entry.getAsObject ()) {
395+ if (auto Kind = Obj->getString (" OutputKind" )) {
396+ if (*Kind != " cached-diagnostics" )
397+ continue ;
398+ }
399+ if (auto Key = Obj->getString (" CacheKey" )) {
400+ if (auto Buffer = loadCachedCompileResultFromCacheKey (
401+ Instance.getObjectStore (), Instance.getActionCache (),
402+ Instance.getDiags (), *Key)) {
403+ if (auto E = CDP->replayCachedDiagnostics (Buffer->getBuffer ())) {
404+ llvm::errs () << " failed to replay cache: "
405+ << toString (std::move (E)) << " \n " ;
406+ return true ;
407+ }
408+ return false ;
409+ }
410+ }
411+ }
412+ }
413+ llvm::errs () << " cannot locate cached diagnostics in file\n " ;
414+ return true ;
415+ };
416+
417+ return llvm::any_of (Inputs, renderDiagsFromFile);
418+ }
419+
353420int swift_cache_tool_main (ArrayRef<const char *> Args, const char *Argv0,
354421 void *MainAddr) {
355422 INITIALIZE_LLVM ();
0 commit comments