18
18
#include " swift/Basic/LLVM.h"
19
19
#include " swift/Basic/LLVMInitialize.h"
20
20
#include " swift/Basic/Version.h"
21
+ #include " swift/Frontend/CachingUtils.h"
21
22
#include " swift/Frontend/CompileJobCacheKey.h"
22
23
#include " swift/Frontend/Frontend.h"
23
24
#include " swift/Frontend/PrintingDiagnosticConsumer.h"
27
28
#include " llvm/CAS/BuiltinUnifiedCASDatabases.h"
28
29
#include " llvm/CAS/ObjectStore.h"
29
30
#include " llvm/Support/JSON.h"
31
+ #include " llvm/Support/MemoryBuffer.h"
30
32
#include < memory>
31
33
32
34
using namespace swift ;
@@ -38,7 +40,15 @@ namespace {
38
40
enum class SwiftCacheToolAction {
39
41
Invalid,
40
42
PrintBaseKey,
41
- PrintOutputKeys
43
+ PrintOutputKeys,
44
+ ValidateOutputs
45
+ };
46
+
47
+ struct OutputEntry {
48
+ std::string InputPath;
49
+ std::string OutputPath;
50
+ std::string OutputKind;
51
+ std::string CacheKey;
42
52
};
43
53
44
54
class SwiftCacheToolInvocation {
@@ -48,6 +58,7 @@ class SwiftCacheToolInvocation {
48
58
PrintingDiagnosticConsumer PDC;
49
59
std::string MainExecutablePath;
50
60
std::string CASPath;
61
+ std::vector<std::string> Inputs;
51
62
std::vector<std::string> FrontendArgs;
52
63
SwiftCacheToolAction ActionKind = SwiftCacheToolAction::Invalid;
53
64
@@ -84,17 +95,19 @@ class SwiftCacheToolInvocation {
84
95
CASPath =
85
96
ParsedArgs.getLastArgValue (OPT_cas_path, getDefaultOnDiskCASPath ());
86
97
98
+ Inputs = ParsedArgs.getAllArgValues (OPT_INPUT);
87
99
FrontendArgs = ParsedArgs.getAllArgValues (OPT__DASH_DASH);
88
100
if (auto *A = ParsedArgs.getLastArg (OPT_cache_tool_action))
89
101
ActionKind =
90
102
llvm::StringSwitch<SwiftCacheToolAction>(A->getValue ())
91
103
.Case (" print-base-key" , SwiftCacheToolAction::PrintBaseKey)
92
104
.Case (" print-output-keys" , SwiftCacheToolAction::PrintOutputKeys)
105
+ .Case (" validate-outputs" , SwiftCacheToolAction::ValidateOutputs)
93
106
.Default (SwiftCacheToolAction::Invalid);
94
107
95
108
if (ActionKind == SwiftCacheToolAction::Invalid) {
96
109
llvm::errs () << " Invalid option specified for -cache-tool-action: "
97
- << " use print-base-key|print-output-keys\n " ;
110
+ << " use print-base-key|print-output-keys|validate-outputs \n " ;
98
111
return 1 ;
99
112
}
100
113
@@ -107,6 +120,8 @@ class SwiftCacheToolInvocation {
107
120
return printBaseKey ();
108
121
case SwiftCacheToolAction::PrintOutputKeys:
109
122
return printOutputKeys ();
123
+ case SwiftCacheToolAction::ValidateOutputs:
124
+ return validateOutputs ();
110
125
case SwiftCacheToolAction::Invalid:
111
126
llvm::report_fatal_error (" invalid action" );
112
127
}
@@ -186,6 +201,7 @@ class SwiftCacheToolInvocation {
186
201
}
187
202
188
203
int printOutputKeys ();
204
+ int validateOutputs ();
189
205
};
190
206
191
207
} // end anonymous namespace
@@ -199,12 +215,6 @@ int SwiftCacheToolInvocation::printOutputKeys() {
199
215
if (!BaseKey)
200
216
return 1 ;
201
217
202
- struct OutputEntry {
203
- std::string InputPath;
204
- std::string OutputPath;
205
- std::string OutputKind;
206
- std::string CacheKey;
207
- };
208
218
std::vector<OutputEntry> OutputKeys;
209
219
bool hasError = false ;
210
220
auto addOutputKey = [&](StringRef InputPath, file_types::ID OutputKind,
@@ -260,6 +270,55 @@ int SwiftCacheToolInvocation::printOutputKeys() {
260
270
return 0 ;
261
271
}
262
272
273
+ int SwiftCacheToolInvocation::validateOutputs () {
274
+ auto DB = llvm::cas::createOnDiskUnifiedCASDatabases (CASPath);
275
+ if (!DB)
276
+ report_fatal_error (DB.takeError ());
277
+
278
+ PrintingDiagnosticConsumer PDC;
279
+ Instance.getDiags ().addConsumer (PDC);
280
+
281
+ auto validateCacheKeysFromFile = [&](const std::string &Path) {
282
+ auto JSONContent = llvm::MemoryBuffer::getFile (Path);
283
+ if (!JSONContent) {
284
+ llvm::errs () << " failed to read " << Path << " : "
285
+ << JSONContent.getError ().message () << " \n " ;
286
+ return true ;
287
+ }
288
+ auto JSONValue = llvm::json::parse ((*JSONContent)->getBuffer ());
289
+ if (!JSONValue) {
290
+ llvm::errs () << " failed to parse " << Path << " : "
291
+ << toString (JSONValue.takeError ()) << " \n " ;
292
+ return true ;
293
+ }
294
+
295
+ auto Keys = JSONValue->getAsArray ();
296
+ if (!Keys) {
297
+ llvm::errs () << " invalid keys format in " << Path << " \n " ;
298
+ return true ;
299
+ }
300
+
301
+ for (const auto & Entry : *Keys) {
302
+ if (auto *Obj = Entry.getAsObject ()) {
303
+ if (auto Key = Obj->getString (" CacheKey" )) {
304
+ if (auto Buffer = loadCachedCompileResultFromCacheKey (
305
+ *DB->first , *DB->second , Instance.getDiags (), *Key))
306
+ continue ;
307
+ llvm::errs () << " failed to find output for cache key " << *Key
308
+ << " \n " ;
309
+ return true ;
310
+ }
311
+ }
312
+ llvm::errs () << " can't read cache key from " << Path << " \n " ;
313
+ return true ;
314
+ }
315
+
316
+ return false ;
317
+ };
318
+
319
+ return llvm::any_of (Inputs, validateCacheKeysFromFile);
320
+ }
321
+
263
322
int swift_cache_tool_main (ArrayRef<const char *> Args, const char *Argv0,
264
323
void *MainAddr) {
265
324
INITIALIZE_LLVM ();
0 commit comments