Skip to content

Commit b326c55

Browse files
[CAS] Full support for make-style dependencies file caching hit
Fully support make-style `.d` dependencies file output by making following improvements: * All correct dependency file render when cache hit for a different output file location. The dependency file should list the correct output path, not the stale output path for the initial compilation * When enable a path prefix mapper to canonicalize the path, the dependency file should render the input file correctly as the input file path on disk. rdar://132250067
1 parent 353a1c2 commit b326c55

File tree

11 files changed

+285
-78
lines changed

11 files changed

+285
-78
lines changed

include/swift/Frontend/CASOutputBackends.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class SwiftCASOutputBackend : public llvm::vfs::OutputBackend {
3838
private:
3939
file_types::ID getOutputFileType(llvm::StringRef Path) const;
4040

41+
/// Return true if the file type is stored into CAS Backend directly.
42+
static bool isStoredDirectly(file_types::ID Kind);
43+
4144
public:
4245
SwiftCASOutputBackend(llvm::cas::ObjectStore &CAS,
4346
llvm::cas::ActionCache &Cache,
@@ -49,6 +52,9 @@ class SwiftCASOutputBackend : public llvm::vfs::OutputBackend {
4952
llvm::Error storeCachedDiagnostics(unsigned InputIndex,
5053
llvm::StringRef Bytes);
5154

55+
llvm::Error storeMakeDependenciesFile(StringRef OutputFilename,
56+
llvm::StringRef Bytes);
57+
5258
/// Store the MCCAS CASID \p ID as the object file output for the input
5359
/// that corresponds to the \p OutputFilename
5460
llvm::Error storeMCCASObjectID(StringRef OutputFilename, llvm::cas::CASID ID);

include/swift/Frontend/CachingUtils.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ createSwiftCachingOutputBackend(
4040

4141
/// Replay the output of the compilation from cache.
4242
/// Return true if outputs are replayed, false otherwise.
43-
bool replayCachedCompilerOutputs(
44-
llvm::cas::ObjectStore &CAS, llvm::cas::ActionCache &Cache,
45-
llvm::cas::ObjectRef BaseKey, DiagnosticEngine &Diag,
46-
const FrontendInputsAndOutputs &InputsAndOutputs,
47-
CachingDiagnosticsProcessor &CDP, bool CacheRemarks, bool UseCASBackend);
43+
bool replayCachedCompilerOutputs(llvm::cas::ObjectStore &CAS,
44+
llvm::cas::ActionCache &Cache,
45+
llvm::cas::ObjectRef BaseKey,
46+
DiagnosticEngine &Diag,
47+
const FrontendOptions &Opts,
48+
CachingDiagnosticsProcessor &CDP,
49+
bool CacheRemarks, bool UseCASBackend);
4850

4951
/// Load the cached compile result from cache.
5052
std::unique_ptr<llvm::MemoryBuffer> loadCachedCompileResultFromCacheKey(
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===--- MakeStyleDependencies.h -- header for emitting dependency files --===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 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+
// This file defines interface for emitting Make Style Dependency Files.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_FRONTEND_MAKESTYLEDEPENDENCIES_H
18+
#define SWIFT_FRONTEND_MAKESTYLEDEPENDENCIES_H
19+
20+
#include "llvm/ADT/StringRef.h"
21+
22+
namespace llvm {
23+
class raw_ostream;
24+
} // namespace llvm
25+
26+
namespace swift {
27+
28+
class CompilerInstance;
29+
class DiagnosticEngine;
30+
class FrontendOptions;
31+
class InputFile;
32+
33+
/// Emit make style dependency file from compiler instance if needed.
34+
bool emitMakeDependenciesIfNeeded(CompilerInstance &instance,
35+
const InputFile &input);
36+
37+
/// Emit make style dependency file from a serialized buffer.
38+
bool emitMakeDependenciesFromSerializedBuffer(llvm::StringRef buffer,
39+
llvm::raw_ostream &os,
40+
const FrontendOptions &opts,
41+
const InputFile &input,
42+
DiagnosticEngine &diags);
43+
44+
} // end namespace swift
45+
46+
#endif

lib/Frontend/CASOutputBackends.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class SwiftCASOutputBackend::Implementation {
7373
auto OutputType = ProducingInput->second.second;
7474

7575
// Uncached output kind.
76-
if (file_types::isProducedFromDiagnostics(OutputType))
76+
if (!isStoredDirectly(OutputType))
7777
return std::make_unique<llvm::vfs::NullOutputFileImpl>();
7878

7979
return std::make_unique<SwiftCASOutputFile>(
@@ -115,6 +115,11 @@ SwiftCASOutputBackend::SwiftCASOutputBackend(
115115

116116
SwiftCASOutputBackend::~SwiftCASOutputBackend() { delete &Impl; }
117117

118+
bool SwiftCASOutputBackend::isStoredDirectly(file_types::ID Kind) {
119+
return !file_types::isProducedFromDiagnostics(Kind) &&
120+
Kind != file_types::TY_Dependencies;
121+
}
122+
118123
IntrusiveRefCntPtr<OutputBackend> SwiftCASOutputBackend::cloneImpl() const {
119124
return makeIntrusiveRefCnt<SwiftCASOutputBackend>(
120125
Impl.CAS, Impl.Cache, Impl.BaseKey, Impl.InputsAndOutputs, Impl.Action);
@@ -142,6 +147,18 @@ Error SwiftCASOutputBackend::storeCachedDiagnostics(unsigned InputIndex,
142147
file_types::ID::TY_CachedDiagnostics);
143148
}
144149

150+
Error SwiftCASOutputBackend::storeMakeDependenciesFile(StringRef OutputFilename,
151+
llvm::StringRef Bytes) {
152+
auto Input = Impl.OutputToInputMap.find(OutputFilename);
153+
if (Input == Impl.OutputToInputMap.end())
154+
return llvm::createStringError("InputIndex for output file not found!");
155+
auto InputIndex = Input->second.first;
156+
assert(Input->second.second == file_types::TY_Dependencies &&
157+
"wrong output type");
158+
return storeImpl(OutputFilename, Bytes, InputIndex,
159+
file_types::TY_Dependencies);
160+
}
161+
145162
Error SwiftCASOutputBackend::storeMCCASObjectID(StringRef OutputFilename,
146163
llvm::cas::CASID ID) {
147164
auto Input = Impl.OutputToInputMap.find(OutputFilename);

lib/Frontend/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_swift_host_library(swiftFrontend STATIC
1515
Frontend.cpp
1616
FrontendInputsAndOutputs.cpp
1717
FrontendOptions.cpp
18+
MakeStyleDependencies.cpp
1819
ModuleInterfaceBuilder.cpp
1920
ModuleInterfaceLoader.cpp
2021
ModuleInterfaceSupport.cpp

lib/Frontend/CachingUtils.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/Frontend/CompileJobCacheKey.h"
2121
#include "swift/Frontend/CompileJobCacheResult.h"
2222
#include "swift/Frontend/FrontendOptions.h"
23+
#include "swift/Frontend/MakeStyleDependencies.h"
2324
#include "swift/Option/Options.h"
2425
#include "clang/CAS/CASOptions.h"
2526
#include "clang/CAS/IncludeTree.h"
@@ -135,19 +136,21 @@ lookupCacheKey(ObjectStore &CAS, ActionCache &Cache, ObjectRef CacheKey) {
135136

136137
bool replayCachedCompilerOutputs(
137138
ObjectStore &CAS, ActionCache &Cache, ObjectRef BaseKey,
138-
DiagnosticEngine &Diag, const FrontendInputsAndOutputs &InputsAndOutputs,
139+
DiagnosticEngine &Diag, const FrontendOptions &Opts,
139140
CachingDiagnosticsProcessor &CDP, bool CacheRemarks, bool UseCASBackend) {
140141
bool CanReplayAllOutput = true;
141142
struct OutputEntry {
142143
std::string Path;
143144
CASID Key;
145+
file_types::ID Kind;
146+
const InputFile &Input;
144147
ObjectProxy Proxy;
145148
};
146149
SmallVector<OutputEntry> OutputProxies;
147150
std::optional<OutputEntry> DiagnosticsOutput;
148-
std::string ObjFile;
149151

150-
auto replayOutputsForInputFile = [&](const std::string &InputPath,
152+
auto replayOutputsForInputFile = [&](const InputFile &Input,
153+
const std::string &InputPath,
151154
unsigned InputIndex,
152155
const DenseMap<file_types::ID,
153156
std::string> &Outputs) {
@@ -190,15 +193,13 @@ bool replayCachedCompilerOutputs(
190193
if (!Proxy)
191194
return Proxy.takeError();
192195

193-
if (Kind == file_types::ID::TY_Object && UseCASBackend)
194-
ObjFile = OutputPath->second;
195-
196196
if (Kind == file_types::ID::TY_CachedDiagnostics) {
197197
assert(!DiagnosticsOutput && "more than 1 diagnotics found");
198-
DiagnosticsOutput = OutputEntry{OutputPath->second, OutID, *Proxy};
198+
DiagnosticsOutput.emplace(
199+
OutputEntry{OutputPath->second, OutID, Kind, Input, *Proxy});
199200
} else
200201
OutputProxies.emplace_back(
201-
OutputEntry{OutputPath->second, OutID, *Proxy});
202+
OutputEntry{OutputPath->second, OutID, Kind, Input, *Proxy});
202203
return Error::success();
203204
})) {
204205
Diag.diagnose(SourceLoc(), diag::error_cas, toString(std::move(Err)));
@@ -211,7 +212,7 @@ bool replayCachedCompilerOutputs(
211212
auto InputPath = Input.getFileName();
212213
DenseMap<file_types::ID, std::string> Outputs;
213214
if (!Input.outputFilename().empty())
214-
Outputs.try_emplace(InputsAndOutputs.getPrincipalOutputType(),
215+
Outputs.try_emplace(Opts.InputsAndOutputs.getPrincipalOutputType(),
215216
Input.outputFilename());
216217

217218
Input.getPrimarySpecificPaths()
@@ -233,15 +234,15 @@ bool replayCachedCompilerOutputs(
233234
Outputs.try_emplace(file_types::ID::TY_CachedDiagnostics,
234235
"<cached-diagnostics>");
235236

236-
return replayOutputsForInputFile(InputPath, InputIndex, Outputs);
237+
return replayOutputsForInputFile(Input, InputPath, InputIndex, Outputs);
237238
};
238239

239-
auto AllInputs = InputsAndOutputs.getAllInputs();
240+
auto AllInputs = Opts.InputsAndOutputs.getAllInputs();
240241
// If there are primary inputs, look up only the primary input files.
241242
// Otherwise, prepare to do cache lookup for all inputs.
242243
for (unsigned Index = 0; Index < AllInputs.size(); ++Index) {
243244
const auto &Input = AllInputs[Index];
244-
if (InputsAndOutputs.hasPrimaryInputs() && !Input.isPrimary())
245+
if (Opts.InputsAndOutputs.hasPrimaryInputs() && !Input.isPrimary())
245246
continue;
246247

247248
replayOutputFromInput(Input, Index);
@@ -255,8 +256,9 @@ bool replayCachedCompilerOutputs(
255256
// diagnostics from first file.
256257
if (!DiagnosticsOutput)
257258
replayOutputsForInputFile(
259+
Opts.InputsAndOutputs.getFirstOutputProducingInput(),
258260
"<cached-diagnostics>",
259-
InputsAndOutputs.getIndexOfFirstOutputProducingInput(),
261+
Opts.InputsAndOutputs.getIndexOfFirstOutputProducingInput(),
260262
{{file_types::ID::TY_CachedDiagnostics, "<cached-diagnostics>"}});
261263

262264
// Check again to make sure diagnostics is fetched successfully.
@@ -287,10 +289,16 @@ bool replayCachedCompilerOutputs(
287289
continue;
288290
}
289291

290-
if (UseCASBackend && Output.Path == ObjFile) {
292+
if (UseCASBackend && Output.Kind == file_types::ID::TY_Object) {
291293
auto Schema = std::make_unique<llvm::mccasformats::v1::MCSchema>(CAS);
292-
if (auto E = Schema->serializeObjectFile(Output.Proxy, *File))
294+
if (auto E = Schema->serializeObjectFile(Output.Proxy, *File)) {
293295
Diag.diagnose(SourceLoc(), diag::error_mccas, toString(std::move(E)));
296+
return false;
297+
}
298+
} else if (Output.Kind == file_types::ID::TY_Dependencies) {
299+
if (emitMakeDependenciesFromSerializedBuffer(
300+
Output.Proxy.getData(), *File, Opts, Output.Input, Diag))
301+
return false;
294302
} else
295303
*File << Output.Proxy.getData();
296304

0 commit comments

Comments
 (0)