Skip to content

Commit 8dabf58

Browse files
Add support for MCCAS in replay logic for swift
This patch adds support for MCCAS when a cache hit is encountered when trying to replay a compilation, and uses the MCCAS serialization code to materialize the object file that is the main output of the compilation.
1 parent 31baf4f commit 8dabf58

File tree

6 files changed

+137
-5
lines changed

6 files changed

+137
-5
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ ERROR(error_opening_output,none,
3232
ERROR(error_closing_output,none,
3333
"error closing '%0' for output: %1", (StringRef, StringRef))
3434

35+
ERROR(error_mccas,none,
36+
"error trying to materialize MCCAS object file: %0", (StringRef))
37+
3538
ERROR(cannot_find_group_info_file,none,
3639
"cannot find group info file at path: '%0'", (StringRef))
3740

include/swift/Frontend/CachingUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ bool replayCachedCompilerOutputs(
4444
llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
4545
llvm::cas::ObjectRef BaseKey, DiagnosticEngine &Diag,
4646
const FrontendInputsAndOutputs &InputsAndOutputs,
47-
CachingDiagnosticsProcessor &CDP, bool CacheRemarks);
47+
CachingDiagnosticsProcessor &CDP, bool CacheRemarks, bool UseCASBackend);
4848

4949
/// Load the cached compile result from cache.
5050
std::unique_ptr<llvm::MemoryBuffer> loadCachedCompileResultFromCacheKey(

lib/Frontend/CachingUtils.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/CAS/HierarchicalTreeBuilder.h"
3030
#include "llvm/CAS/ObjectStore.h"
3131
#include "llvm/CAS/TreeEntry.h"
32+
#include "llvm/MCCAS/MCCASObjectV1.h"
3233
#include "llvm/Option/ArgList.h"
3334
#include "llvm/Option/OptTable.h"
3435
#include "llvm/Support/Debug.h"
@@ -134,7 +135,7 @@ lookupCacheKey(ObjectStore &CAS, ActionCache &Cache, ObjectRef CacheKey) {
134135
bool replayCachedCompilerOutputs(
135136
ObjectStore &CAS, ActionCache &Cache, ObjectRef BaseKey,
136137
DiagnosticEngine &Diag, const FrontendInputsAndOutputs &InputsAndOutputs,
137-
CachingDiagnosticsProcessor &CDP, bool CacheRemarks) {
138+
CachingDiagnosticsProcessor &CDP, bool CacheRemarks, bool UseCASBackend) {
138139
bool CanReplayAllOutput = true;
139140
struct OutputEntry {
140141
std::string Path;
@@ -143,6 +144,7 @@ bool replayCachedCompilerOutputs(
143144
};
144145
SmallVector<OutputEntry> OutputProxies;
145146
std::optional<OutputEntry> DiagnosticsOutput;
147+
std::string ObjFile;
146148

147149
auto replayOutputsForInputFile = [&](const std::string &InputPath,
148150
unsigned InputIndex,
@@ -176,7 +178,6 @@ bool replayCachedCompilerOutputs(
176178
CachedResultLoader Loader(CAS, **OutputRef);
177179
LLVM_DEBUG(llvm::dbgs() << "DEBUG: lookup cache key \'" << OutID.toString()
178180
<< "\' for input \'" << InputPath << "\n";);
179-
180181
if (auto Err = Loader.replay([&](file_types::ID Kind,
181182
ObjectRef Ref) -> Error {
182183
auto OutputPath = Outputs.find(Kind);
@@ -188,6 +189,9 @@ bool replayCachedCompilerOutputs(
188189
if (!Proxy)
189190
return Proxy.takeError();
190191

192+
if (Kind == file_types::ID::TY_Object && UseCASBackend)
193+
ObjFile = OutputPath->second;
194+
191195
if (Kind == file_types::ID::TY_CachedDiagnostics) {
192196
assert(!DiagnosticsOutput && "more than 1 diagnotics found");
193197
DiagnosticsOutput = OutputEntry{OutputPath->second, OutID, *Proxy};
@@ -281,7 +285,14 @@ bool replayCachedCompilerOutputs(
281285
toString(File.takeError()));
282286
continue;
283287
}
284-
*File << Output.Proxy.getData();
288+
289+
if (UseCASBackend && Output.Path == ObjFile) {
290+
auto Schema = std::make_unique<llvm::mccasformats::v1::MCSchema>(CAS);
291+
if (auto E = Schema->serializeObjectFile(Output.Proxy, *File))
292+
Diag.diagnose(SourceLoc(), diag::error_mccas, toString(std::move(E)));
293+
} else
294+
*File << Output.Proxy.getData();
295+
285296
if (auto E = File->keep()) {
286297
Diag.diagnose(SourceLoc(), diag::error_closing_output, Output.Path,
287298
toString(std::move(E)));

lib/FrontendTool/FrontendTool.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,8 @@ static bool tryReplayCompilerResults(CompilerInstance &Instance) {
14781478
Instance.getObjectStore(), Instance.getActionCache(),
14791479
*Instance.getCompilerBaseKey(), Instance.getDiags(),
14801480
Instance.getInvocation().getFrontendOptions().InputsAndOutputs, *CDP,
1481-
Instance.getInvocation().getCASOptions().EnableCachingRemarks);
1481+
Instance.getInvocation().getCASOptions().EnableCachingRemarks,
1482+
Instance.getInvocation().getIRGenOptions().UseCASBackend);
14821483

14831484
// If we didn't replay successfully, re-start capture.
14841485
if (!replayed)

test/CAS/cache_replay_mccas.swift

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// REQUIRES: OS=macosx
2+
// RUN: %empty-directory(%t)
3+
// RUN: split-file %s %t
4+
5+
// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -module-cache-path %t/clang-module-cache \
6+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
7+
// RUN: %t/test.swift -I %t -o %t/deps.json -cache-compile-job -cas-backend -cas-backend-mode=verify -cas-path %t/cas
8+
9+
/// Check clang module
10+
// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:Dummy > %t/dummy.cmd
11+
// RUN: %swift_frontend_plain @%t/dummy.cmd -Rcache-compile-job 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
12+
// RUN: %swift_frontend_plain @%t/dummy.cmd -Rcache-compile-job 2>&1 | %FileCheck --check-prefix=CACHE-HIT-CLANG %s
13+
14+
// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
15+
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid
16+
17+
// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd
18+
// RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd
19+
// RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd
20+
// RUN: echo "\"-disable-implicit-swift-modules\"" >> %t/MyApp.cmd
21+
// RUN: echo "\"-parse-stdlib\"" >> %t/MyApp.cmd
22+
// RUN: echo "\"-explicit-swift-module-map-file\"" >> %t/MyApp.cmd
23+
// RUN: echo "\"@%t/map.casid\"" >> %t/MyApp.cmd
24+
25+
/// Run the command first time, expect cache miss.
26+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
27+
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
28+
// RUN: test -f %t/test.o
29+
// RUN: test -f %t/test.d
30+
// RUN: test -f %t/Test.swiftmodule
31+
32+
/// Expect cache hit for second time.
33+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c -emit-dependencies \
34+
// RUN: -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
35+
// RUN: test -f %t/test.o
36+
// RUN: test -f %t/test.d
37+
// RUN: test -f %t/Test.swiftmodule
38+
39+
/// Expect cache miss a subset of outputs.
40+
// RUN %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c \
41+
// RUN -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
42+
43+
/// Cache hit for retry.
44+
// RUN %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c \
45+
// RUN -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
46+
47+
/// Skip cache
48+
// RUN %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job -cache-disable-replay %t/test.swift -O -emit-module -emit-module-path %t/Test.swiftmodule -c \
49+
// RUN -module-name Test -o %t/test.o -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --allow-empty --check-prefix=SKIP-CACHE %s
50+
51+
// CACHE-MISS: remark: cache miss for input
52+
// CACHE-HIT: remark: replay output file '<cached-diagnostics>': key 'llvmcas://{{.*}}'
53+
// CACHE-HIT: remark: replay output file '{{.*}}{{/|\\}}test.o': key 'llvmcas://{{.*}}'
54+
// CACHE-HIT: remark: replay output file '{{.*}}{{/|\\}}Test.swiftmodule': key 'llvmcas://{{.*}}'
55+
// CACHE-HIT-CLANG: remark: replay output file '<cached-diagnostics>': key 'llvmcas://{{.*}}'
56+
// CACHE-HIT-CLANG: remark: replay output file '{{.*}}{{/|\\}}Dummy-{{.*}}.pcm': key 'llvmcas://{{.*}}'
57+
// SKIP-CACHE-NOT: remark:
58+
59+
//--- test.swift
60+
import Dummy
61+
func testFunc() {}
62+
63+
//--- module.modulemap
64+
module Dummy {
65+
umbrella header "Dummy.h"
66+
}
67+
68+
//--- Dummy.h
69+
void dummy(void);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// REQUIRES: OS=macosx
2+
// RUN: %empty-directory(%t)
3+
// RUN: split-file %s %t
4+
5+
// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O \
6+
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
7+
// RUN: %t/test.swift %t/foo.swift -o %t/deps.json -cache-compile-job -cas-backend -cas-backend-mode=verify -cas-path %t/cas
8+
9+
// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
10+
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid
11+
12+
// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd
13+
// RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd
14+
// RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd
15+
// RUN: echo "\"-parse-stdlib\"" >> %t/MyApp.cmd
16+
17+
/// Test compile multiple inputs with batch mode.
18+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift %t/foo.swift -emit-module -o %t/Test.swiftmodule \
19+
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
20+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job -primary-file %t/test.swift %t/foo.swift -c -o %t/test.o \
21+
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
22+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift -primary-file %t/foo.swift -c -o %t/foo.o \
23+
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-MISS %s
24+
// RUN: test -f %t/test.o
25+
// RUN: test -f %t/foo.o
26+
// RUN: test -f %t/Test.swiftmodule
27+
28+
/// Expect cache hit second time
29+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift %t/foo.swift -emit-module -o %t/Test.swiftmodule \
30+
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
31+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job -primary-file %t/test.swift %t/foo.swift -c -o %t/test.o \
32+
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
33+
// RUN: %target-swift-frontend -cache-compile-job -cas-backend -cas-backend-mode=verify -Rcache-compile-job %t/test.swift -primary-file %t/foo.swift -c -o %t/foo.o \
34+
// RUN: -module-name Test -cas-path %t/cas @%t/MyApp.cmd 2>&1 | %FileCheck --check-prefix=CACHE-HIT %s
35+
// RUN: test -f %t/test.o
36+
// RUN: test -f %t/foo.o
37+
// RUN: test -f %t/Test.swiftmodule
38+
39+
//--- test.swift
40+
func testFunc() {}
41+
42+
//--- foo.swift
43+
func foo() {}
44+
45+
// CACHE-MISS: remark: cache miss for input
46+
// CACHE-MISS-NOT: remark: replay output file
47+
// CACHE-HIT: remark: replay output file
48+
// CACHE-HIT-NOT: remark: cache miss for input

0 commit comments

Comments
 (0)