Skip to content

Commit 5be305e

Browse files
[CompilerCaching] Teach CachedDiagnostics to replay with prefix map
Teach CachedDiagnosticsProcessor to replay diagnostics for all consumers with a different path using a path prefix map. This allows diagnostics to be replayed for the actual path on disk after the scanner canonicalized the path for compilation.
1 parent 7b89afb commit 5be305e

File tree

5 files changed

+52
-13
lines changed

5 files changed

+52
-13
lines changed

include/swift/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ class FrontendOptions {
148148
/// CacheKey for input file.
149149
std::string InputFileKey;
150150

151+
/// CacheReplay PrefixMap.
152+
std::vector<std::string> CacheReplayPrefixMap;
153+
151154
/// Number of retry opening an input file if the previous opening returns
152155
/// bad file descriptor error.
153156
unsigned BadFileDescriptorRetryCount = 0;

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,6 +1865,10 @@ def scanner_prefix_map_toolchain : Separate<["-"], "scanner-prefix-map-toolchain
18651865
Flags<[NewDriverOnlyOption]>,
18661866
HelpText<"Remap paths within toolchain directory reported by dependency scanner">, MetaVarName<"<path>">;
18671867

1868+
def cache_replay_prefix_map: Separate<["-"], "cache-replay-prefix-map">,
1869+
Flags<[FrontendOption, NoDriverOption, CacheInvariant]>,
1870+
HelpText<"Remap paths when replaying outputs from cache">, MetaVarName<"<prefix=replacement>">;
1871+
18681872
// END ONLY SUPPORTED IN NEW DRIVER
18691873

18701874

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ bool ArgsToFrontendOptionsConverter::convert(
270270
Opts.CASFSRootIDs = Args.getAllArgValues(OPT_cas_fs);
271271
Opts.ClangIncludeTrees = Args.getAllArgValues(OPT_clang_include_tree_root);
272272
Opts.InputFileKey = Args.getLastArgValue(OPT_input_file_key);
273+
Opts.CacheReplayPrefixMap = Args.getAllArgValues(OPT_cache_replay_prefix_map);
273274

274275
if (Opts.EnableCaching && Opts.CASFSRootIDs.empty() &&
275276
Opts.ClangIncludeTrees.empty() &&

lib/Frontend/CachedDiagnostics.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/Support/Compression.h"
3030
#include "llvm/Support/Debug.h"
3131
#include "llvm/Support/Error.h"
32+
#include "llvm/Support/PrefixMapper.h"
3233
#include "llvm/Support/SMLoc.h"
3334
#include "llvm/Support/VirtualFileSystem.h"
3435
#include "llvm/Support/YAMLTraits.h"
@@ -98,8 +99,9 @@ struct SerializedGeneratedFileInfo {
9899
};
99100

100101
struct DiagnosticSerializer {
101-
DiagnosticSerializer(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
102-
: SrcMgr(FS) {}
102+
DiagnosticSerializer(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
103+
llvm::PrefixMapper &Mapper)
104+
: SrcMgr(FS), Mapper(Mapper) {}
103105

104106
using ReplayFunc = llvm::function_ref<llvm::Error(const DiagnosticInfo &)>;
105107

@@ -111,10 +113,11 @@ struct DiagnosticSerializer {
111113
static llvm::Error
112114
emitDiagnosticsFromCached(llvm::StringRef Buffer, SourceManager &SrcMgr,
113115
DiagnosticEngine &Diags,
116+
llvm::PrefixMapper &Mapper,
114117
const FrontendInputsAndOutputs &InAndOut) {
115118
// Create a new DiagnosticSerializer since this cannot be shared with a
116119
// serialization instance.
117-
DiagnosticSerializer DS(SrcMgr.getFileSystem());
120+
DiagnosticSerializer DS(SrcMgr.getFileSystem(), Mapper);
118121
DS.addInputsToSourceMgr(InAndOut);
119122
return DS.doEmitFromCached(Buffer, Diags);
120123
}
@@ -128,7 +131,7 @@ struct DiagnosticSerializer {
128131
// has references to input files to find subconsumer.
129132
auto addInputToSourceMgr = [&](const InputFile &Input) {
130133
if (Input.getFileName() != "-")
131-
SrcMgr.getExternalSourceBufferID(Input.getFileName());
134+
SrcMgr.getExternalSourceBufferID(remapFilePath(Input.getFileName()));
132135
return false;
133136
};
134137
InAndOut.forEachInputProducingSupplementaryOutput(addInputToSourceMgr);
@@ -163,6 +166,9 @@ struct DiagnosticSerializer {
163166
unsigned deserializeFile(const SerializedFile &File);
164167
llvm::Error deserializeVirtualFile(const SerializedVirtualFile &VF);
165168
llvm::Error deserializeGeneratedFileInfo(const SerializedGeneratedFileInfo &Info);
169+
std::string remapFilePath(StringRef Path) {
170+
return Mapper.mapToString(Path);
171+
}
166172

167173
public:
168174
std::vector<SerializedDiagnosticInfo> DiagInfos;
@@ -176,6 +182,7 @@ struct DiagnosticSerializer {
176182

177183
// Serializing SourceManager.
178184
SourceManager SrcMgr;
185+
llvm::PrefixMapper &Mapper;
179186

180187
// Mapping of the FileID between SourceManager from CompilerInstance vs.
181188
// the serialized FileID in cached diagnostics. Lookup tables are
@@ -482,10 +489,19 @@ DiagnosticSerializer::deserializeFixIt(const SerializedFixIt &FI) {
482489

483490
unsigned DiagnosticSerializer::deserializeFile(const SerializedFile &File) {
484491
assert(File.IncludeLoc.FileID == 0 && "IncludeLoc not supported yet");
485-
return File.Content.empty()
486-
? SrcMgr.getExternalSourceBufferID(File.FileName)
487-
: SrcMgr.addNewSourceBuffer(llvm::MemoryBuffer::getMemBufferCopy(
488-
File.Content, File.FileName));
492+
auto FileName = remapFilePath(File.FileName);
493+
if (File.Content.empty() && FileName == File.FileName)
494+
return SrcMgr.getExternalSourceBufferID(FileName);
495+
496+
std::unique_ptr<llvm::MemoryBuffer> Content;
497+
if (!File.Content.empty())
498+
Content = llvm::MemoryBuffer::getMemBufferCopy(File.Content, FileName);
499+
else if (auto InputFileOrErr = swift::vfs::getFileOrSTDIN(
500+
*SrcMgr.getFileSystem(), File.FileName))
501+
Content = llvm::MemoryBuffer::getMemBufferCopy(
502+
(*InputFileOrErr)->getBuffer(), FileName);
503+
504+
return Content ? SrcMgr.addNewSourceBuffer(std::move(Content)) : 0u;
489505
}
490506

491507
llvm::Error
@@ -495,8 +511,8 @@ DiagnosticSerializer::deserializeVirtualFile(const SerializedVirtualFile &VF) {
495511
return Range.takeError();
496512
unsigned Length = (const char *)Range->getEnd().getOpaquePointerValue() -
497513
(const char *)Range->getStart().getOpaquePointerValue();
498-
SrcMgr.createVirtualFile(Range->getStart(), VF.FileName, VF.LineOffset,
499-
Length);
514+
auto FileName = remapFilePath(VF.FileName);
515+
SrcMgr.createVirtualFile(Range->getStart(), FileName, VF.LineOffset, Length);
500516
return llvm::Error::success();
501517
}
502518

@@ -625,7 +641,14 @@ class CachingDiagnosticsProcessor::Implementation
625641
: InstanceSourceMgr(Instance.getSourceMgr()),
626642
InAndOut(
627643
Instance.getInvocation().getFrontendOptions().InputsAndOutputs),
628-
Diags(Instance.getDiags()) {}
644+
Diags(Instance.getDiags()) {
645+
SmallVector<llvm::MappedPrefix, 4> Prefixes;
646+
llvm::MappedPrefix::transformJoinedIfValid(
647+
Instance.getInvocation().getFrontendOptions().CacheReplayPrefixMap,
648+
Prefixes);
649+
Mapper.addRange(Prefixes);
650+
Mapper.sort();
651+
}
629652
~Implementation() {}
630653

631654
void startDiagnosticCapture() {
@@ -648,7 +671,7 @@ class CachingDiagnosticsProcessor::Implementation
648671

649672
llvm::Error replayCachedDiagnostics(llvm::StringRef Buffer) {
650673
return DiagnosticSerializer::emitDiagnosticsFromCached(
651-
Buffer, getDiagnosticSourceMgr(), Diags, InAndOut);
674+
Buffer, getDiagnosticSourceMgr(), Diags, Mapper, InAndOut);
652675
}
653676

654677
void handleDiagnostic(SourceManager &SM,
@@ -698,7 +721,7 @@ class CachingDiagnosticsProcessor::Implementation
698721
// file system changes on later diagnostics.
699722
if (!Serializer) {
700723
Serializer.reset(
701-
new DiagnosticSerializer(InstanceSourceMgr.getFileSystem()));
724+
new DiagnosticSerializer(InstanceSourceMgr.getFileSystem(), Mapper));
702725
Serializer->addInputsToSourceMgr(InAndOut);
703726
}
704727

@@ -717,6 +740,7 @@ class CachingDiagnosticsProcessor::Implementation
717740
SourceManager &InstanceSourceMgr;
718741
const FrontendInputsAndOutputs &InAndOut;
719742
DiagnosticEngine &Diags;
743+
llvm::PrefixMapper Mapper;
720744

721745
llvm::unique_function<bool(StringRef)> serializedOutputCallback;
722746

test/CAS/cached_diagnostics.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@
1919

2020
// Verify the serialized diags have the right magic at the top.
2121
// CHECK-SERIALIZED: DIA
22+
23+
/// Check path remapping.
24+
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action render-diags %t/cache_key.json -- %target-swift-frontend -c -cache-compile-job -cas-path %t/cas -allow-unstable-cache-key-for-testing %s \
25+
// RUN: -import-objc-header %S/Inputs/objc.h -emit-module -emit-module-path %t/test.swiftmodule -cache-replay-prefix-map %S=/^test 2>&1 | %FileCheck %s --check-prefix REMAP
26+
27+
// REMAP: /^test/Inputs/objc.h:3:2: warning: warning in bridging header
28+
// REMAP: /^test/cached_diagnostics.swift:10:10: warning: this is a warning

0 commit comments

Comments
 (0)