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,6 +85,7 @@ struct SerializedDiagnosticInfo {
82
85
struct SerializedFile {
83
86
std::string FileName;
84
87
SerializedSourceLoc IncludeLoc = SerializedSourceLoc();
88
+ std::string ContentCASID;
85
89
StringRef Content;
86
90
};
87
91
@@ -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,40 @@ 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
+
143
+ // Fetch the source buffer from original SourceManager and create a
144
+ // serialized file from it.
145
+ auto Idx = SM.getExternalSourceBufferID (Path);
146
+ if (Idx != 0 )
147
+ getFileIDFromBufferID (SM, Idx);
148
+
135
149
return false ;
136
150
};
137
- InAndOut.forEachInputProducingSupplementaryOutput (addInputToSourceMgr);
138
- InAndOut.forEachNonPrimaryInput (addInputToSourceMgr);
151
+ InAndOut.forEachInput (addInputToSourceMgr);
139
152
}
140
153
141
154
private:
@@ -169,7 +182,7 @@ struct DiagnosticSerializer {
169
182
DiagnosticStorage &, ReplayFunc);
170
183
171
184
// Deserialize File and return the bufferID in serializing SourceManager.
172
- unsigned deserializeFile (const SerializedFile &File);
185
+ llvm::Expected< unsigned > deserializeFile (const SerializedFile &File);
173
186
llvm::Error deserializeVirtualFile (const SerializedVirtualFile &VF);
174
187
llvm::Error deserializeGeneratedFileInfo (const SerializedGeneratedFileInfo &Info);
175
188
std::string remapFilePath (StringRef Path) {
@@ -190,6 +203,9 @@ struct DiagnosticSerializer {
190
203
SourceManager SrcMgr;
191
204
llvm::PrefixMapper &Mapper;
192
205
206
+ // CAS for file system backing.
207
+ llvm::cas::ObjectStore &CAS;
208
+
193
209
// Mapping of the FileID between SourceManager from CompilerInstance vs.
194
210
// the serialized FileID in cached diagnostics. Lookup tables are
195
211
// per-SourceManager to handle diagnostics from all sub-instances which
@@ -248,6 +264,7 @@ struct MappingTraits<SerializedFile> {
248
264
io.mapRequired (" Name" , F.FileName );
249
265
io.mapOptional (" IncludeLoc" , F.IncludeLoc , SerializedSourceLoc ());
250
266
io.mapOptional (" Content" , F.Content , StringRef ());
267
+ io.mapOptional (" CASID" , F.ContentCASID , " " );
251
268
}
252
269
};
253
270
@@ -302,25 +319,29 @@ void DiagnosticSerializer::handleDiagnostic(SourceManager &SM,
302
319
303
320
unsigned DiagnosticSerializer::getFileIDFromBufferID (SourceManager &SM,
304
321
unsigned Idx) {
305
- auto &Buf = SM.getLLVMSourceMgr ().getBufferInfo (Idx);
306
- auto Filename = Buf.Buffer ->getBufferIdentifier ();
307
- bool IsFSBacked = SM.getFileSystem ()->exists (Filename);
308
-
309
322
// See if the file is already constructed.
310
323
auto &Allocated = FileMapper[&SM];
311
324
auto ID = Allocated.find (Idx);
312
325
if (ID != Allocated.end ())
313
326
return ID->second ;
314
327
328
+ auto &Buf = SM.getLLVMSourceMgr ().getBufferInfo (Idx);
329
+ auto Filename = Buf.Buffer ->getBufferIdentifier ();
330
+ bool IsFileBacked = SM.getFileSystem ()->exists (Filename);
331
+
315
332
// Construct and add to files. If there is an IncludeLoc, the file from
316
333
// IncludeLoc is added before current file.
317
334
assert (CurrentFileID == Files.size () && " File index mismatch" );
318
- StringRef FileContent = IsFSBacked ? StringRef () : Buf.Buffer ->getBuffer ();
335
+
336
+ StringRef FileContent = Buf.Buffer ->getBuffer ();
319
337
SerializedFile File = {Filename.str (),
320
338
convertSourceLoc (SM, SourceLoc (Buf.IncludeLoc )),
321
- FileContent};
339
+ {},
340
+ IsFileBacked ? " " : FileContent};
341
+
322
342
// Add file to serializing source manager.
323
- FileMapper[&SrcMgr].insert ({CurrentFileID, deserializeFile (File)});
343
+ unsigned NewIdx = SrcMgr.addMemBufferCopy (Buf.Buffer .get ());
344
+ FileMapper[&SrcMgr].insert ({CurrentFileID, NewIdx});
324
345
325
346
Files.emplace_back (std::move (File));
326
347
Allocated.insert ({Idx, ++CurrentFileID});
@@ -495,21 +516,26 @@ DiagnosticSerializer::deserializeFixIt(const SerializedFixIt &FI) {
495
516
return DiagnosticInfo::FixIt (*Range, FI.Text , {});
496
517
}
497
518
498
- unsigned DiagnosticSerializer::deserializeFile (const SerializedFile &File) {
519
+ llvm::Expected<unsigned >
520
+ DiagnosticSerializer::deserializeFile (const SerializedFile &File) {
499
521
assert (File.IncludeLoc .FileID == 0 && " IncludeLoc not supported yet" );
500
522
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 ;
523
+
524
+ if (!File.ContentCASID .empty ()) {
525
+ auto ID = CAS.parseID (File.ContentCASID );
526
+ if (!ID)
527
+ return ID.takeError ();
528
+
529
+ auto Proxy = CAS.getProxy (*ID);
530
+ if (!Proxy)
531
+ return Proxy.takeError ();
532
+
533
+ auto Content = Proxy->getMemoryBuffer (FileName);
534
+ return SrcMgr.addNewSourceBuffer (std::move (Content));
535
+ }
536
+
537
+ auto Content = llvm::MemoryBuffer::getMemBufferCopy (File.Content , FileName);
538
+ return SrcMgr.addNewSourceBuffer (std::move (Content));
513
539
}
514
540
515
541
llvm::Error
@@ -599,6 +625,32 @@ llvm::Error DiagnosticSerializer::deserializeDiagnosticInfo(
599
625
600
626
llvm::Error
601
627
DiagnosticSerializer::serializeEmittedDiagnostics (llvm::raw_ostream &os) {
628
+ // Convert all file backed source file into CASIDs.
629
+ for (auto &File : Files) {
630
+ if (!File.Content .empty () || !File.ContentCASID .empty ())
631
+ continue ;
632
+
633
+ auto Ref =
634
+ SrcMgr.getFileSystem ()->getObjectRefForFileContent (File.FileName );
635
+ if (!Ref)
636
+ return llvm::createFileError (File.FileName , Ref.getError ());
637
+
638
+ if (*Ref) {
639
+ File.ContentCASID = CAS.getID (**Ref).toString ();
640
+ continue ;
641
+ }
642
+
643
+ // Probably a file system that is not CAS based. Ingest the buffer.
644
+ auto Buf = SrcMgr.getFileSystem ()->getBufferForFile (File.FileName );
645
+ if (!Buf)
646
+ return llvm::createFileError (File.FileName , Buf.getError ());
647
+
648
+ auto BufRef = CAS.storeFromString ({}, (*Buf)->getBuffer ());
649
+ if (!BufRef)
650
+ return llvm::createFileError (File.FileName , BufRef.takeError ());
651
+ File.ContentCASID = CAS.getID (*BufRef).toString ();
652
+ }
653
+
602
654
llvm::yaml::Output yout (os);
603
655
yout << *this ;
604
656
return llvm::Error::success ();
@@ -616,8 +668,10 @@ llvm::Error DiagnosticSerializer::doEmitFromCached(llvm::StringRef Buffer,
616
668
unsigned ID = 0 ;
617
669
for (auto &File : Files) {
618
670
assert (File.IncludeLoc .FileID == 0 && " IncludeLoc not supported yet" );
619
- unsigned Idx = deserializeFile (File);
620
- FileMapper[&SrcMgr].insert ({ID++, Idx});
671
+ auto Idx = deserializeFile (File);
672
+ if (!Idx)
673
+ return Idx.takeError ();
674
+ FileMapper[&SrcMgr].insert ({ID++, *Idx});
621
675
}
622
676
623
677
for (auto &VF : VFiles) {
@@ -651,7 +705,7 @@ class CachingDiagnosticsProcessor::Implementation
651
705
: InstanceSourceMgr(Instance.getSourceMgr()),
652
706
InAndOut (
653
707
Instance.getInvocation().getFrontendOptions().InputsAndOutputs),
654
- Diags(Instance.getDiags()) {
708
+ Diags(Instance.getDiags()), CAS(*Instance.getSharedCASInstance()) {
655
709
SmallVector<llvm::MappedPrefix, 4 > Prefixes;
656
710
llvm::MappedPrefix::transformJoinedIfValid (
657
711
Instance.getInvocation ().getFrontendOptions ().CacheReplayPrefixMap ,
@@ -681,7 +735,7 @@ class CachingDiagnosticsProcessor::Implementation
681
735
682
736
llvm::Error replayCachedDiagnostics (llvm::StringRef Buffer) {
683
737
return DiagnosticSerializer::emitDiagnosticsFromCached (
684
- Buffer, getDiagnosticSourceMgr (), Diags, Mapper, InAndOut);
738
+ Buffer, Diags, Mapper, CAS , InAndOut);
685
739
}
686
740
687
741
void handleDiagnostic (SourceManager &SM,
@@ -691,7 +745,7 @@ class CachingDiagnosticsProcessor::Implementation
691
745
" Caching for a different file system" );
692
746
Serializer.handleDiagnostic (SM, Info, [&](const DiagnosticInfo &Info) {
693
747
for (auto *Diag : OrigConsumers)
694
- Diag->handleDiagnostic (getDiagnosticSourceMgr (), Info);
748
+ Diag->handleDiagnostic (Serializer. getSourceMgr (), Info);
695
749
return llvm::Error::success ();
696
750
});
697
751
}
@@ -718,10 +772,6 @@ class CachingDiagnosticsProcessor::Implementation
718
772
}
719
773
720
774
private:
721
- SourceManager &getDiagnosticSourceMgr () {
722
- return getSerializer ().getSourceMgr ();
723
- }
724
-
725
775
DiagnosticSerializer &getSerializer () {
726
776
// If the DiagnosticSerializer is not setup, create it. It cannot
727
777
// be created on the creation of CachingDiagnosticsProcessor because the
@@ -730,9 +780,9 @@ class CachingDiagnosticsProcessor::Implementation
730
780
// compiler instance on the first diagnostics and assert if the underlying
731
781
// file system changes on later diagnostics.
732
782
if (!Serializer) {
733
- Serializer.reset (
734
- new DiagnosticSerializer ( InstanceSourceMgr.getFileSystem (), Mapper));
735
- Serializer->addInputsToSourceMgr (InAndOut);
783
+ Serializer.reset (new DiagnosticSerializer (
784
+ InstanceSourceMgr.getFileSystem (), Mapper, CAS ));
785
+ Serializer->addInputsToSourceMgr (InstanceSourceMgr, InAndOut);
736
786
}
737
787
738
788
return *Serializer;
@@ -751,6 +801,7 @@ class CachingDiagnosticsProcessor::Implementation
751
801
const FrontendInputsAndOutputs &InAndOut;
752
802
DiagnosticEngine &Diags;
753
803
llvm::PrefixMapper Mapper;
804
+ llvm::cas::ObjectStore &CAS;
754
805
755
806
llvm::unique_function<bool (StringRef)> serializedOutputCallback;
756
807
0 commit comments