Skip to content

Commit 7dc4973

Browse files
Mirror outputs into CAS using CASOutputBackend
When `-enable-cas` option is used, mirror the output into CAS so it can be fetched from CAS with the cache key in the future.
1 parent 11e6017 commit 7dc4973

File tree

10 files changed

+416
-9
lines changed

10 files changed

+416
-9
lines changed

include/swift/Frontend/CachingUtils.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===--- CachingUtils.h -----------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_FRONTEND_CACHINGUTILS_H
14+
#define SWIFT_FRONTEND_CACHINGUTILS_H
15+
16+
#include "swift/Frontend/FrontendInputsAndOutputs.h"
17+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
18+
#include "llvm/CAS/ActionCache.h"
19+
#include "llvm/CAS/ObjectStore.h"
20+
#include "llvm/CAS/CASReference.h"
21+
#include "llvm/Support/VirtualOutputBackend.h"
22+
#include <memory>
23+
24+
namespace swift {
25+
26+
/// Create a swift caching output backend that stores the output from
27+
/// compiler into a CAS.
28+
llvm::IntrusiveRefCntPtr<llvm::vfs::OutputBackend>
29+
createSwiftCachingOutputBackend(
30+
llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
31+
llvm::cas::ObjectRef BaseKey,
32+
const FrontendInputsAndOutputs &InputsAndOutputs);
33+
34+
/// Load the cached compile result from cache.
35+
std::unique_ptr<llvm::MemoryBuffer> loadCachedCompileResultFromCacheKey(
36+
llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
37+
DiagnosticEngine &Diag, llvm::StringRef CacheKey,
38+
llvm::StringRef Filename = "");
39+
40+
/// Store compiler output.
41+
llvm::Error storeCachedCompilerOutput(llvm::cas::ObjectStore &CAS,
42+
llvm::cas::ActionCache &Cache,
43+
StringRef Path, StringRef Bytes,
44+
llvm::cas::ObjectRef BaseKey,
45+
StringRef CorrespondingInput,
46+
file_types::ID OutputKind);
47+
48+
}
49+
50+
#endif

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,9 @@ class CompilerInstance {
631631
/// i.e. if it can be found.
632632
bool canImportCxxShim() const;
633633

634+
/// Whether this compiler instance supports caching.
635+
bool supportCaching() const;
636+
634637
/// Gets the SourceFile which is the primary input for this CompilerInstance.
635638
/// \returns the primary SourceFile, or nullptr if there is no primary input;
636639
/// if there are _multiple_ primary inputs, fails with an assertion.

include/swift/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ class FrontendOptions {
445445
/// \return true if the given action requires input files to be provided.
446446
static bool doesActionPerformEndOfPipelineActions(ActionType action);
447447

448+
/// \return true if the given action supports caching.
449+
static bool supportCompilationCaching(ActionType action);
450+
448451
/// Return a hash code of any components from these options that should
449452
/// contribute to a Swift Bridging PCH hash.
450453
llvm::hash_code getPCHHashComponents() const {

include/swift/Option/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1674,7 +1674,7 @@ def use_interface_for_module: Separate<["-", "--"], "use-interface-for-module">,
16741674
def cache_tool_action: JoinedOrSeparate<["-"], "cache-tool-action">,
16751675
Flags<[NoDriverOption, SwiftCacheToolOption]>,
16761676
HelpText<"Swift Cache Tool Action Kind">,
1677-
MetaVarName<"<print-base-key|print-output-keys>">;
1677+
MetaVarName<"<print-base-key|print-output-keys|validate-outputs>">;
16781678

16791679
// ONLY SUPPORTED IN NEW DRIVER
16801680

lib/DriverTool/swift_cache_tool_main.cpp

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/Basic/LLVM.h"
1919
#include "swift/Basic/LLVMInitialize.h"
2020
#include "swift/Basic/Version.h"
21+
#include "swift/Frontend/CachingUtils.h"
2122
#include "swift/Frontend/CompileJobCacheKey.h"
2223
#include "swift/Frontend/Frontend.h"
2324
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
@@ -27,6 +28,7 @@
2728
#include "llvm/CAS/BuiltinUnifiedCASDatabases.h"
2829
#include "llvm/CAS/ObjectStore.h"
2930
#include "llvm/Support/JSON.h"
31+
#include "llvm/Support/MemoryBuffer.h"
3032
#include <memory>
3133

3234
using namespace swift;
@@ -38,7 +40,15 @@ namespace {
3840
enum class SwiftCacheToolAction {
3941
Invalid,
4042
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;
4252
};
4353

4454
class SwiftCacheToolInvocation {
@@ -48,6 +58,7 @@ class SwiftCacheToolInvocation {
4858
PrintingDiagnosticConsumer PDC;
4959
std::string MainExecutablePath;
5060
std::string CASPath;
61+
std::vector<std::string> Inputs;
5162
std::vector<std::string> FrontendArgs;
5263
SwiftCacheToolAction ActionKind = SwiftCacheToolAction::Invalid;
5364

@@ -84,17 +95,19 @@ class SwiftCacheToolInvocation {
8495
CASPath =
8596
ParsedArgs.getLastArgValue(OPT_cas_path, getDefaultOnDiskCASPath());
8697

98+
Inputs = ParsedArgs.getAllArgValues(OPT_INPUT);
8799
FrontendArgs = ParsedArgs.getAllArgValues(OPT__DASH_DASH);
88100
if (auto *A = ParsedArgs.getLastArg(OPT_cache_tool_action))
89101
ActionKind =
90102
llvm::StringSwitch<SwiftCacheToolAction>(A->getValue())
91103
.Case("print-base-key", SwiftCacheToolAction::PrintBaseKey)
92104
.Case("print-output-keys", SwiftCacheToolAction::PrintOutputKeys)
105+
.Case("validate-outputs", SwiftCacheToolAction::ValidateOutputs)
93106
.Default(SwiftCacheToolAction::Invalid);
94107

95108
if (ActionKind == SwiftCacheToolAction::Invalid) {
96109
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";
98111
return 1;
99112
}
100113

@@ -107,6 +120,8 @@ class SwiftCacheToolInvocation {
107120
return printBaseKey();
108121
case SwiftCacheToolAction::PrintOutputKeys:
109122
return printOutputKeys();
123+
case SwiftCacheToolAction::ValidateOutputs:
124+
return validateOutputs();
110125
case SwiftCacheToolAction::Invalid:
111126
llvm::report_fatal_error("invalid action");
112127
}
@@ -186,6 +201,7 @@ class SwiftCacheToolInvocation {
186201
}
187202

188203
int printOutputKeys();
204+
int validateOutputs();
189205
};
190206

191207
} // end anonymous namespace
@@ -199,12 +215,6 @@ int SwiftCacheToolInvocation::printOutputKeys() {
199215
if (!BaseKey)
200216
return 1;
201217

202-
struct OutputEntry {
203-
std::string InputPath;
204-
std::string OutputPath;
205-
std::string OutputKind;
206-
std::string CacheKey;
207-
};
208218
std::vector<OutputEntry> OutputKeys;
209219
bool hasError = false;
210220
auto addOutputKey = [&](StringRef InputPath, file_types::ID OutputKind,
@@ -260,6 +270,55 @@ int SwiftCacheToolInvocation::printOutputKeys() {
260270
return 0;
261271
}
262272

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+
263322
int swift_cache_tool_main(ArrayRef<const char *> Args, const char *Argv0,
264323
void *MainAddr) {
265324
INITIALIZE_LLVM();

lib/Frontend/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_swift_host_library(swiftFrontend STATIC
33
ArgsToFrontendInputsConverter.cpp
44
ArgsToFrontendOptionsConverter.cpp
55
ArgsToFrontendOutputsConverter.cpp
6+
CachingUtils.cpp
67
CompileJobCacheKey.cpp
78
CompilerInvocation.cpp
89
DependencyVerifier.cpp

0 commit comments

Comments
 (0)