Skip to content

Commit 278eba5

Browse files
Merge pull request #68946 from cachemeifyoucan/eng/PR-cache-key-rework
[Caching] Change swift cache key computation
2 parents e4d57c3 + 6c30976 commit 278eba5

25 files changed

+1012
-353
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -437,17 +437,6 @@ typedef struct swiftscan_cas_options_s *swiftscan_cas_options_t;
437437
/// ActionCache.
438438
typedef struct swiftscan_cas_s *swiftscan_cas_t;
439439

440-
/// Enum types for output types for cache key computation.
441-
/// TODO: complete the list.
442-
typedef enum {
443-
SWIFTSCAN_OUTPUT_TYPE_OBJECT = 0,
444-
SWIFTSCAN_OUTPUT_TYPE_SWIFTMODULE = 1,
445-
SWIFTSCAN_OUTPUT_TYPE_SWIFTINTERFACE = 2,
446-
SWIFTSCAN_OUTPUT_TYPE_SWIFTPRIVATEINTERFACE = 3,
447-
SWIFTSCAN_OUTPUT_TYPE_CLANG_MODULE = 4,
448-
SWIFTSCAN_OUTPUT_TYPE_CLANG_PCH = 5
449-
} swiftscan_output_kind_t;
450-
451440
/// Create a \c CASOptions for creating CAS inside scanner specified.
452441
SWIFTSCAN_PUBLIC swiftscan_cas_options_t swiftscan_cas_options_create(void);
453442

@@ -489,13 +478,15 @@ SWIFTSCAN_PUBLIC swiftscan_string_ref_t
489478
swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, unsigned size,
490479
swiftscan_string_ref_t *error);
491480

492-
/// Compute \c CacheKey for output of \c kind from the compiler invocation \c
493-
/// argc and \c argv with \c input. Return \c CacheKey as string.
481+
/// Compute \c CacheKey for the outputs of a primary input file from a compiler
482+
/// invocation with command-line \c argc and \c argv. When primary input file
483+
/// is not available for compilation, e.g., using WMO, primary file is the first
484+
/// swift input on the command-line by convention. Return \c CacheKey as string.
494485
/// If error happens, the error message is returned via `error` parameter, and
495486
/// caller needs to free the error message via `swiftscan_string_dispose`.
496-
SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_compute_cache_key(
497-
swiftscan_cas_t cas, int argc, const char **argv, const char *input,
498-
swiftscan_output_kind_t kind, swiftscan_string_ref_t *error);
487+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
488+
swiftscan_cache_compute_key(swiftscan_cas_t cas, int argc, const char **argv,
489+
const char *input, swiftscan_string_ref_t *error);
499490

500491
//===----------------------------------------------------------------------===//
501492

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ ERROR(error_caching_no_cas_fs, none,
494494
ERROR(error_prefix_mapping, none, "cannot create scanner prefix mapping: '%0'", (StringRef))
495495

496496
REMARK(replay_output, none, "replay output file '%0': key '%1'", (StringRef, StringRef))
497-
REMARK(output_cache_miss, none, "cache miss output file '%0': key '%1'", (StringRef, StringRef))
497+
REMARK(output_cache_miss, none, "cache miss for input file '%0': key '%1'", (StringRef, StringRef))
498498

499499
// CAS related diagnostics
500500
ERROR(error_invalid_cas_id, none, "invalid CASID '%0' (%1)", (StringRef, StringRef))

include/swift/Basic/FileTypes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ bool isAfterLLVM(ID Id);
5858
/// These need to be passed to the Swift frontend
5959
bool isPartOfSwiftCompilation(ID Id);
6060

61+
/// Returns true of the type of the output is produced from a diagnostic engine.
62+
bool isProducedFromDiagnostics(ID Id);
63+
6164
static inline void forAllTypes(llvm::function_ref<void(file_types::ID)> fn) {
6265
for (uint8_t i = 0; i < static_cast<uint8_t>(TY_INVALID); ++i)
6366
fn(static_cast<ID>(i));
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===------CASOutputBackends.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_CASOUTPUTBACKENDS_H
14+
#define SWIFT_FRONTEND_CASOUTPUTBACKENDS_H
15+
16+
#include "swift/Frontend/FrontendInputsAndOutputs.h"
17+
#include "swift/Frontend/FrontendOptions.h"
18+
#include "llvm/CAS/ActionCache.h"
19+
#include "llvm/CAS/ObjectStore.h"
20+
#include "llvm/Support/VirtualOutputBackends.h"
21+
#include "llvm/Support/VirtualOutputFile.h"
22+
23+
namespace swift::cas {
24+
25+
class SwiftCASOutputBackend : public llvm::vfs::OutputBackend {
26+
void anchor() override;
27+
28+
protected:
29+
llvm::IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override;
30+
31+
llvm::Expected<std::unique_ptr<llvm::vfs::OutputFileImpl>>
32+
createFileImpl(llvm::StringRef ResolvedPath,
33+
llvm::Optional<llvm::vfs::OutputConfig> Config) override;
34+
35+
virtual llvm::Error storeImpl(llvm::StringRef Path, llvm::StringRef Bytes,
36+
llvm::StringRef CorrespondingInput,
37+
file_types::ID OutputKind);
38+
39+
private:
40+
file_types::ID getOutputFileType(llvm::StringRef Path) const;
41+
42+
public:
43+
SwiftCASOutputBackend(llvm::cas::ObjectStore &CAS,
44+
llvm::cas::ActionCache &Cache,
45+
llvm::cas::ObjectRef BaseKey,
46+
const FrontendInputsAndOutputs &InputsAndOutputs,
47+
FrontendOptions::ActionType Action);
48+
~SwiftCASOutputBackend();
49+
50+
llvm::Error storeCachedDiagnostics(llvm::StringRef InputFile,
51+
llvm::StringRef Bytes);
52+
53+
private:
54+
class Implementation;
55+
Implementation &Impl;
56+
};
57+
58+
} // end namespace swift::cas
59+
60+
#endif

include/swift/Frontend/CachingUtils.h

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
#ifndef SWIFT_FRONTEND_CACHINGUTILS_H
1414
#define SWIFT_FRONTEND_CACHINGUTILS_H
1515

16+
#include "swift/Frontend/CASOutputBackends.h"
1617
#include "swift/Frontend/CachedDiagnostics.h"
1718
#include "swift/Frontend/FrontendInputsAndOutputs.h"
19+
#include "swift/Frontend/FrontendOptions.h"
1820
#include "clang/CAS/CASOptions.h"
1921
#include "llvm/ADT/IntrusiveRefCntPtr.h"
2022
#include "llvm/CAS/ActionCache.h"
@@ -29,11 +31,12 @@ namespace swift {
2931

3032
/// Create a swift caching output backend that stores the output from
3133
/// compiler into a CAS.
32-
llvm::IntrusiveRefCntPtr<llvm::vfs::OutputBackend>
34+
llvm::IntrusiveRefCntPtr<cas::SwiftCASOutputBackend>
3335
createSwiftCachingOutputBackend(
3436
llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
3537
llvm::cas::ObjectRef BaseKey,
36-
const FrontendInputsAndOutputs &InputsAndOutputs);
38+
const FrontendInputsAndOutputs &InputsAndOutputs,
39+
FrontendOptions::ActionType Action);
3740

3841
/// Replay the output of the compilation from cache.
3942
/// Return true if outputs are replayed, false otherwise.
@@ -46,24 +49,35 @@ bool replayCachedCompilerOutputs(
4649
/// Load the cached compile result from cache.
4750
std::unique_ptr<llvm::MemoryBuffer> loadCachedCompileResultFromCacheKey(
4851
llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
49-
DiagnosticEngine &Diag, llvm::StringRef CacheKey,
52+
DiagnosticEngine &Diag, llvm::StringRef CacheKey, file_types::ID Type,
5053
llvm::StringRef Filename = "");
5154

52-
/// Store compiler output.
53-
llvm::Error storeCachedCompilerOutput(llvm::cas::ObjectStore &CAS,
54-
llvm::cas::ActionCache &Cache,
55-
StringRef Path, StringRef Bytes,
56-
llvm::cas::ObjectRef BaseKey,
57-
StringRef CorrespondingInput,
58-
file_types::ID OutputKind);
59-
6055
llvm::Expected<llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
6156
createCASFileSystem(llvm::cas::ObjectStore &CAS, ArrayRef<std::string> FSRoots,
6257
ArrayRef<std::string> IncludeTreeRoots);
6358

6459
std::vector<std::string> remapPathsFromCommandLine(
6560
ArrayRef<std::string> Args,
6661
llvm::function_ref<std::string(StringRef)> RemapCallback);
67-
} // namespace swift
62+
63+
namespace cas {
64+
class CachedResultLoader {
65+
public:
66+
CachedResultLoader(llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
67+
llvm::cas::ObjectRef CacheKey)
68+
: CAS(CAS), Cache(Cache), CacheKey(CacheKey) {}
69+
70+
using CallbackTy =
71+
llvm::function_ref<llvm::Error(file_types::ID, llvm::cas::ObjectRef)>;
72+
// Replay the cached result, return false if a cache miss happened.
73+
llvm::Expected<bool> replay(CallbackTy Callback);
74+
75+
private:
76+
llvm::cas::ObjectStore &CAS;
77+
llvm::cas::ActionCache &Cache;
78+
llvm::cas::ObjectRef CacheKey;
79+
};
80+
} // end namespace cas
81+
} // end namespace swift
6882

6983
#endif

include/swift/Frontend/CompileJobCacheKey.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ createCompileJobBaseCacheKey(llvm::cas::ObjectStore &CAS,
4141
llvm::Expected<llvm::cas::ObjectRef>
4242
createCompileJobCacheKeyForOutput(llvm::cas::ObjectStore &CAS,
4343
llvm::cas::ObjectRef BaseKey,
44-
StringRef ProducingInput,
45-
file_types::ID OutputType);
44+
StringRef ProducingInput);
4645
} // namespace swift
4746

4847
#endif
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//===------CompileJobCacheResult.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_COMPILEJOBCACHERESULT_H
14+
#define SWIFT_FRONTEND_COMPILEJOBCACHERESULT_H
15+
16+
#include "swift/Basic/FileTypes.h"
17+
#include "llvm/CAS/CASNodeSchema.h"
18+
#include "llvm/CAS/ObjectStore.h"
19+
20+
namespace swift::cas {
21+
22+
class CompileJobResultSchema;
23+
class CompileJobCacheResult : public llvm::cas::ObjectProxy {
24+
public:
25+
/// A single output file or stream.
26+
struct Output {
27+
/// The CAS object for this output.
28+
llvm::cas::ObjectRef Object;
29+
/// The output kind.
30+
file_types::ID Kind;
31+
32+
bool operator==(const Output &Other) const {
33+
return Object == Other.Object && Kind == Other.Kind;
34+
}
35+
};
36+
37+
/// Retrieves each \c Output from this result.
38+
llvm::Error
39+
forEachOutput(llvm::function_ref<llvm::Error(Output)> Callback) const;
40+
41+
/// Loads all outputs concurrently and passes the resulting \c ObjectProxy
42+
/// objects to \p Callback. If there was an error during loading then the
43+
/// callback will not be invoked.
44+
llvm::Error forEachLoadedOutput(
45+
llvm::function_ref<llvm::Error(Output, std::optional<ObjectProxy>)>
46+
Callback);
47+
48+
size_t getNumOutputs() const;
49+
50+
Output getOutput(size_t I) const;
51+
52+
/// Retrieves a specific output specified by \p Kind, if it exists.
53+
llvm::Optional<Output> getOutput(file_types::ID Kind) const;
54+
55+
/// Print this result to \p OS.
56+
llvm::Error print(llvm::raw_ostream &OS);
57+
58+
/// Helper to build a \c CompileJobCacheResult from individual outputs.
59+
class Builder {
60+
public:
61+
Builder();
62+
~Builder();
63+
/// Treat outputs added for \p Path as having the given \p Kind. Otherwise
64+
/// they will have kind \c Unknown.
65+
void addKindMap(file_types::ID Kind, StringRef Path);
66+
/// Add an output with an explicit \p Kind.
67+
void addOutput(file_types::ID Kind, llvm::cas::ObjectRef Object);
68+
/// Add an output for the given \p Path. There must be a a kind map for it.
69+
llvm::Error addOutput(StringRef Path, llvm::cas::ObjectRef Object);
70+
/// Build a single \c ObjectRef representing the provided outputs. The
71+
/// result can be used with \c CompileJobResultSchema to retrieve the
72+
/// original outputs.
73+
llvm::Expected<llvm::cas::ObjectRef> build(llvm::cas::ObjectStore &CAS);
74+
75+
private:
76+
struct PrivateImpl;
77+
PrivateImpl &Impl;
78+
};
79+
80+
private:
81+
llvm::cas::ObjectRef getOutputObject(size_t I) const;
82+
llvm::cas::ObjectRef getPathsListRef() const;
83+
file_types::ID getOutputKind(size_t I) const;
84+
llvm::Expected<llvm::cas::ObjectRef> getOutputPath(size_t I) const;
85+
86+
private:
87+
friend class CompileJobResultSchema;
88+
CompileJobCacheResult(const ObjectProxy &);
89+
};
90+
91+
class CompileJobResultSchema
92+
: public llvm::RTTIExtends<CompileJobResultSchema, llvm::cas::NodeSchema> {
93+
public:
94+
static char ID;
95+
96+
CompileJobResultSchema(llvm::cas::ObjectStore &CAS);
97+
98+
/// Attempt to load \p Ref as a \c CompileJobCacheResult if it matches the
99+
/// schema.
100+
llvm::Expected<CompileJobCacheResult> load(llvm::cas::ObjectRef Ref) const;
101+
102+
bool isRootNode(const CompileJobCacheResult::ObjectProxy &Node) const final;
103+
bool isNode(const CompileJobCacheResult::ObjectProxy &Node) const final;
104+
105+
/// Get this schema's marker node.
106+
llvm::cas::ObjectRef getKindRef() const { return KindRef; }
107+
108+
private:
109+
llvm::cas::ObjectRef KindRef;
110+
};
111+
112+
} // namespace swift::cas
113+
114+
#endif

include/swift/Frontend/Frontend.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/Basic/LangOptions.h"
3131
#include "swift/Basic/SourceManager.h"
3232
#include "swift/ClangImporter/ClangImporter.h"
33+
#include "swift/Frontend/CASOutputBackends.h"
3334
#include "swift/Frontend/CachedDiagnostics.h"
3435
#include "swift/Frontend/DiagnosticVerifier.h"
3536
#include "swift/Frontend/FrontendOptions.h"
@@ -483,6 +484,10 @@ class CompilerInstance {
483484
/// Virtual OutputBackend.
484485
llvm::IntrusiveRefCntPtr<llvm::vfs::OutputBackend> OutputBackend = nullptr;
485486

487+
/// CAS OutputBackend.
488+
llvm::IntrusiveRefCntPtr<swift::cas::SwiftCASOutputBackend> CASOutputBackend =
489+
nullptr;
490+
486491
/// The verification output backend.
487492
using HashBackendTy = llvm::vfs::HashingOutputBackend<llvm::BLAKE3>;
488493
llvm::IntrusiveRefCntPtr<HashBackendTy> HashBackend;
@@ -537,6 +542,10 @@ class CompilerInstance {
537542
llvm::vfs::OutputBackend &getOutputBackend() const {
538543
return *OutputBackend;
539544
}
545+
swift::cas::SwiftCASOutputBackend &getCASOutputBackend() const {
546+
return *CASOutputBackend;
547+
}
548+
540549
void
541550
setOutputBackend(llvm::IntrusiveRefCntPtr<llvm::vfs::OutputBackend> Backend) {
542551
OutputBackend = std::move(Backend);

0 commit comments

Comments
 (0)