24
24
#include " swift/Frontend/FrontendInputsAndOutputs.h"
25
25
#include " llvm/ADT/IntrusiveRefCntPtr.h"
26
26
#include " llvm/ADT/STLExtras.h"
27
+ #include " llvm/ADT/StringExtras.h"
27
28
#include " llvm/ADT/StringRef.h"
28
29
#include " llvm/ADT/TinyPtrVector.h"
30
+ #include " llvm/CAS/ObjectStore.h"
29
31
#include " llvm/Support/Compression.h"
30
32
#include " llvm/Support/Debug.h"
31
33
#include " llvm/Support/Error.h"
34
+ #include " llvm/Support/MemoryBuffer.h"
32
35
#include " llvm/Support/PrefixMapper.h"
33
36
#include " llvm/Support/SMLoc.h"
34
37
#include " llvm/Support/VirtualFileSystem.h"
@@ -82,7 +85,8 @@ struct SerializedDiagnosticInfo {
82
85
struct SerializedFile {
83
86
std::string FileName;
84
87
SerializedSourceLoc IncludeLoc = SerializedSourceLoc();
85
- StringRef Content;
88
+ bool IsFileBacked;
89
+ std::string Content;
86
90
};
87
91
88
92
struct SerializedVirtualFile {
@@ -100,8 +104,8 @@ struct SerializedGeneratedFileInfo {
100
104
101
105
struct DiagnosticSerializer {
102
106
DiagnosticSerializer (llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
103
- llvm::PrefixMapper &Mapper)
104
- : SrcMgr(FS), Mapper(Mapper) {}
107
+ llvm::PrefixMapper &Mapper, llvm::cas::ObjectStore &CAS )
108
+ : SrcMgr(FS), Mapper(Mapper), CAS(CAS) {}
105
109
106
110
using ReplayFunc = llvm::function_ref<llvm::Error(const DiagnosticInfo &)>;
107
111
@@ -111,31 +115,36 @@ struct DiagnosticSerializer {
111
115
llvm::Error serializeEmittedDiagnostics (llvm::raw_ostream &os);
112
116
113
117
static llvm::Error
114
- emitDiagnosticsFromCached (llvm::StringRef Buffer, SourceManager &SrcMgr,
115
- DiagnosticEngine &Diags,
116
- llvm::PrefixMapper &Mapper ,
118
+ emitDiagnosticsFromCached (llvm::StringRef Buffer,
119
+ DiagnosticEngine &Diags, llvm::PrefixMapper &Mapper,
120
+ llvm::cas::ObjectStore &CAS ,
117
121
const FrontendInputsAndOutputs &InAndOut) {
118
122
// Create a new DiagnosticSerializer since this cannot be shared with a
119
- // serialization instance.
120
- DiagnosticSerializer DS (SrcMgr.getFileSystem (), Mapper);
121
- DS.addInputsToSourceMgr (InAndOut);
123
+ // serialization instance. Using an empty in-memory file system as
124
+ // underlying file system because the replay logic should not touch file
125
+ // system.
126
+ auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
127
+ DiagnosticSerializer DS (std::move (FS), Mapper, CAS);
122
128
return DS.doEmitFromCached (Buffer, Diags);
123
129
}
124
130
125
131
SourceManager &getSourceMgr () { return SrcMgr; }
126
132
127
- void addInputsToSourceMgr (const FrontendInputsAndOutputs &InAndOut) {
133
+ void addInputsToSourceMgr (SourceManager &SM,
134
+ const FrontendInputsAndOutputs &InAndOut) {
128
135
// Extract all the input file names so they can be added to the source
129
136
// manager when replaying the diagnostics. All input files are needed even
130
137
// they don't contain diagnostics because FileSpecificDiagConsumer need
131
138
// has references to input files to find subconsumer.
132
139
auto addInputToSourceMgr = [&](const InputFile &Input) {
133
- if (Input.getFileName () != " -" )
134
- SrcMgr.getExternalSourceBufferID (remapFilePath (Input.getFileName ()));
140
+ auto Path = remapFilePath (Input.getFileName ());
141
+ SrcMgr.getExternalSourceBufferID (Path);
142
+ auto Idx = SM.getExternalSourceBufferID (Path);
143
+ if (Idx != 0 )
144
+ getFileIDFromBufferID (SM, Idx);
135
145
return false ;
136
146
};
137
- InAndOut.forEachInputProducingSupplementaryOutput (addInputToSourceMgr);
138
- InAndOut.forEachNonPrimaryInput (addInputToSourceMgr);
147
+ InAndOut.forEachInput (addInputToSourceMgr);
139
148
}
140
149
141
150
private:
@@ -169,7 +178,7 @@ struct DiagnosticSerializer {
169
178
DiagnosticStorage &, ReplayFunc);
170
179
171
180
// Deserialize File and return the bufferID in serializing SourceManager.
172
- unsigned deserializeFile (const SerializedFile &File);
181
+ llvm::Expected< unsigned > deserializeFile (const SerializedFile &File);
173
182
llvm::Error deserializeVirtualFile (const SerializedVirtualFile &VF);
174
183
llvm::Error deserializeGeneratedFileInfo (const SerializedGeneratedFileInfo &Info);
175
184
std::string remapFilePath (StringRef Path) {
@@ -190,6 +199,9 @@ struct DiagnosticSerializer {
190
199
SourceManager SrcMgr;
191
200
llvm::PrefixMapper &Mapper;
192
201
202
+ // CAS for file system backing.
203
+ llvm::cas::ObjectStore &CAS;
204
+
193
205
// Mapping of the FileID between SourceManager from CompilerInstance vs.
194
206
// the serialized FileID in cached diagnostics. Lookup tables are
195
207
// per-SourceManager to handle diagnostics from all sub-instances which
@@ -247,7 +259,8 @@ struct MappingTraits<SerializedFile> {
247
259
static void mapping (IO &io, SerializedFile &F) {
248
260
io.mapRequired (" Name" , F.FileName );
249
261
io.mapOptional (" IncludeLoc" , F.IncludeLoc , SerializedSourceLoc ());
250
- io.mapOptional (" Content" , F.Content , StringRef ());
262
+ io.mapOptional (" FileBacked" , F.IsFileBacked , false );
263
+ io.mapRequired (" Content" , F.Content );
251
264
}
252
265
};
253
266
@@ -302,25 +315,28 @@ void DiagnosticSerializer::handleDiagnostic(SourceManager &SM,
302
315
303
316
unsigned DiagnosticSerializer::getFileIDFromBufferID (SourceManager &SM,
304
317
unsigned Idx) {
305
- auto &Buf = SM.getLLVMSourceMgr ().getBufferInfo (Idx);
306
- auto Filename = Buf.Buffer ->getBufferIdentifier ();
307
- bool IsFSBacked = SM.getFileSystem ()->exists (Filename);
308
-
309
318
// See if the file is already constructed.
310
319
auto &Allocated = FileMapper[&SM];
311
320
auto ID = Allocated.find (Idx);
312
321
if (ID != Allocated.end ())
313
322
return ID->second ;
314
323
324
+ auto &Buf = SM.getLLVMSourceMgr ().getBufferInfo (Idx);
325
+ auto Filename = Buf.Buffer ->getBufferIdentifier ();
326
+ bool IsFileBacked = SM.getFileSystem ()->exists (Filename);
327
+
315
328
// Construct and add to files. If there is an IncludeLoc, the file from
316
329
// IncludeLoc is added before current file.
317
330
assert (CurrentFileID == Files.size () && " File index mismatch" );
318
- StringRef FileContent = IsFSBacked ? StringRef () : Buf.Buffer ->getBuffer ();
331
+
332
+ StringRef FileContent = Buf.Buffer ->getBuffer ();
319
333
SerializedFile File = {Filename.str (),
320
334
convertSourceLoc (SM, SourceLoc (Buf.IncludeLoc )),
321
- FileContent};
335
+ IsFileBacked, IsFileBacked ? " " : FileContent.str ()};
336
+
322
337
// Add file to serializing source manager.
323
- FileMapper[&SrcMgr].insert ({CurrentFileID, deserializeFile (File)});
338
+ unsigned NewIdx = SrcMgr.addMemBufferCopy (Buf.Buffer .get ());
339
+ FileMapper[&SrcMgr].insert ({CurrentFileID, NewIdx});
324
340
325
341
Files.emplace_back (std::move (File));
326
342
Allocated.insert ({Idx, ++CurrentFileID});
@@ -495,21 +511,26 @@ DiagnosticSerializer::deserializeFixIt(const SerializedFixIt &FI) {
495
511
return DiagnosticInfo::FixIt (*Range, FI.Text , {});
496
512
}
497
513
498
- unsigned DiagnosticSerializer::deserializeFile (const SerializedFile &File) {
514
+ llvm::Expected<unsigned >
515
+ DiagnosticSerializer::deserializeFile (const SerializedFile &File) {
499
516
assert (File.IncludeLoc .FileID == 0 && " IncludeLoc not supported yet" );
500
517
auto FileName = remapFilePath (File.FileName );
501
- if (File.Content .empty () && FileName == File.FileName )
502
- return SrcMgr.getExternalSourceBufferID (FileName);
503
-
504
- std::unique_ptr<llvm::MemoryBuffer> Content;
505
- if (!File.Content .empty ())
506
- Content = llvm::MemoryBuffer::getMemBufferCopy (File.Content , FileName);
507
- else if (auto InputFileOrErr = swift::vfs::getFileOrSTDIN (
508
- *SrcMgr.getFileSystem (), File.FileName ))
509
- Content = llvm::MemoryBuffer::getMemBufferCopy (
510
- (*InputFileOrErr)->getBuffer (), FileName);
511
-
512
- return Content ? SrcMgr.addNewSourceBuffer (std::move (Content)) : 0u ;
518
+
519
+ if (File.IsFileBacked ) {
520
+ auto ID = CAS.parseID (File.Content );
521
+ if (!ID)
522
+ return ID.takeError ();
523
+
524
+ auto Proxy = CAS.getProxy (*ID);
525
+ if (!Proxy)
526
+ return Proxy.takeError ();
527
+
528
+ auto Content = Proxy->getMemoryBuffer (FileName);
529
+ return SrcMgr.addNewSourceBuffer (std::move (Content));
530
+ }
531
+
532
+ auto Content = llvm::MemoryBuffer::getMemBufferCopy (File.Content , FileName);
533
+ return SrcMgr.addNewSourceBuffer (std::move (Content));
513
534
}
514
535
515
536
llvm::Error
@@ -599,6 +620,33 @@ llvm::Error DiagnosticSerializer::deserializeDiagnosticInfo(
599
620
600
621
llvm::Error
601
622
DiagnosticSerializer::serializeEmittedDiagnostics (llvm::raw_ostream &os) {
623
+ // Convert all file backed source file into CASIDs.
624
+ for (auto &File : Files) {
625
+ if (!File.IsFileBacked || !File.Content .empty ())
626
+ continue ;
627
+
628
+ auto Ref =
629
+ SrcMgr.getFileSystem ()->getObjectRefForFileContent (File.FileName );
630
+ if (!Ref)
631
+ return llvm::createFileError (File.FileName , Ref.getError ());
632
+
633
+ if (*Ref) {
634
+ auto CASID = CAS.getID (**Ref);
635
+ File.Content = CASID.toString ();
636
+ continue ;
637
+ }
638
+
639
+ // Probably a file system that is not CAS based. Ingest the buffer.
640
+ auto Buf = SrcMgr.getFileSystem ()->getBufferForFile (File.FileName );
641
+ if (!Buf)
642
+ return llvm::createFileError (File.FileName , Buf.getError ());
643
+
644
+ auto BufRef = CAS.storeFromString ({}, (*Buf)->getBuffer ());
645
+ if (!BufRef)
646
+ return llvm::createFileError (File.FileName , BufRef.takeError ());
647
+ File.Content = CAS.getID (*BufRef).toString ();
648
+ }
649
+
602
650
llvm::yaml::Output yout (os);
603
651
yout << *this ;
604
652
return llvm::Error::success ();
@@ -616,8 +664,10 @@ llvm::Error DiagnosticSerializer::doEmitFromCached(llvm::StringRef Buffer,
616
664
unsigned ID = 0 ;
617
665
for (auto &File : Files) {
618
666
assert (File.IncludeLoc .FileID == 0 && " IncludeLoc not supported yet" );
619
- unsigned Idx = deserializeFile (File);
620
- FileMapper[&SrcMgr].insert ({ID++, Idx});
667
+ auto Idx = deserializeFile (File);
668
+ if (!Idx)
669
+ return Idx.takeError ();
670
+ FileMapper[&SrcMgr].insert ({ID++, *Idx});
621
671
}
622
672
623
673
for (auto &VF : VFiles) {
@@ -651,7 +701,7 @@ class CachingDiagnosticsProcessor::Implementation
651
701
: InstanceSourceMgr(Instance.getSourceMgr()),
652
702
InAndOut (
653
703
Instance.getInvocation().getFrontendOptions().InputsAndOutputs),
654
- Diags(Instance.getDiags()) {
704
+ Diags(Instance.getDiags()), CAS(*Instance.getSharedCASInstance()) {
655
705
SmallVector<llvm::MappedPrefix, 4 > Prefixes;
656
706
llvm::MappedPrefix::transformJoinedIfValid (
657
707
Instance.getInvocation ().getFrontendOptions ().CacheReplayPrefixMap ,
@@ -681,7 +731,7 @@ class CachingDiagnosticsProcessor::Implementation
681
731
682
732
llvm::Error replayCachedDiagnostics (llvm::StringRef Buffer) {
683
733
return DiagnosticSerializer::emitDiagnosticsFromCached (
684
- Buffer, getDiagnosticSourceMgr (), Diags, Mapper, InAndOut);
734
+ Buffer, Diags, Mapper, CAS , InAndOut);
685
735
}
686
736
687
737
void handleDiagnostic (SourceManager &SM,
@@ -691,7 +741,7 @@ class CachingDiagnosticsProcessor::Implementation
691
741
" Caching for a different file system" );
692
742
Serializer.handleDiagnostic (SM, Info, [&](const DiagnosticInfo &Info) {
693
743
for (auto *Diag : OrigConsumers)
694
- Diag->handleDiagnostic (getDiagnosticSourceMgr (), Info);
744
+ Diag->handleDiagnostic (Serializer. getSourceMgr (), Info);
695
745
return llvm::Error::success ();
696
746
});
697
747
}
@@ -718,10 +768,6 @@ class CachingDiagnosticsProcessor::Implementation
718
768
}
719
769
720
770
private:
721
- SourceManager &getDiagnosticSourceMgr () {
722
- return getSerializer ().getSourceMgr ();
723
- }
724
-
725
771
DiagnosticSerializer &getSerializer () {
726
772
// If the DiagnosticSerializer is not setup, create it. It cannot
727
773
// be created on the creation of CachingDiagnosticsProcessor because the
@@ -730,9 +776,9 @@ class CachingDiagnosticsProcessor::Implementation
730
776
// compiler instance on the first diagnostics and assert if the underlying
731
777
// file system changes on later diagnostics.
732
778
if (!Serializer) {
733
- Serializer.reset (
734
- new DiagnosticSerializer ( InstanceSourceMgr.getFileSystem (), Mapper));
735
- Serializer->addInputsToSourceMgr (InAndOut);
779
+ Serializer.reset (new DiagnosticSerializer (
780
+ InstanceSourceMgr.getFileSystem (), Mapper, CAS ));
781
+ Serializer->addInputsToSourceMgr (InstanceSourceMgr, InAndOut);
736
782
}
737
783
738
784
return *Serializer;
@@ -751,6 +797,7 @@ class CachingDiagnosticsProcessor::Implementation
751
797
const FrontendInputsAndOutputs &InAndOut;
752
798
DiagnosticEngine &Diags;
753
799
llvm::PrefixMapper Mapper;
800
+ llvm::cas::ObjectStore &CAS;
754
801
755
802
llvm::unique_function<bool (StringRef)> serializedOutputCallback;
756
803
0 commit comments