@@ -20,6 +20,8 @@ using namespace dependencies;
20
20
using llvm::Error;
21
21
22
22
namespace {
23
+ class IncludeTreeBuilder ;
24
+
23
25
class IncludeTreeActionController : public CallbackActionController {
24
26
public:
25
27
IncludeTreeActionController (cas::ObjectStore &DB,
@@ -47,21 +49,54 @@ class IncludeTreeActionController : public CallbackActionController {
47
49
Error finalize (CompilerInstance &ScanInstance,
48
50
CompilerInvocation &NewInvocation) override ;
49
51
50
- Expected<cas::ObjectRef> getObjectForFile (Preprocessor &PP, FileID FID);
51
- Expected<cas::ObjectRef>
52
- getObjectForFileNonCached (FileManager &FM, const SrcMgr::FileInfo &FI);
53
- Expected<cas::ObjectRef> getObjectForBuffer (const SrcMgr::FileInfo &FI);
54
- Expected<cas::ObjectRef> addToFileList (FileManager &FM, const FileEntry *FE);
52
+ private:
53
+ IncludeTreeBuilder ¤t () {
54
+ assert (!BuilderStack.empty ());
55
+ return *BuilderStack.back ();
56
+ }
57
+
58
+ private:
59
+ cas::ObjectStore &DB;
60
+ CASOptions CASOpts;
61
+ DepscanPrefixMapping PrefixMapping;
62
+ llvm::PrefixMapper PrefixMapper;
63
+ SmallVector<std::unique_ptr<IncludeTreeBuilder>> BuilderStack;
64
+ std::optional<cas::IncludeTreeRoot> IncludeTreeResult;
65
+ };
55
66
67
+ // / Callbacks for building an include-tree for a given translation unit or
68
+ // / module. The \c IncludeTreeActionController is responsiblee for pushing and
69
+ // / popping builders from the stack as modules are required.
70
+ class IncludeTreeBuilder {
71
+ public:
72
+ IncludeTreeBuilder (cas::ObjectStore &DB, llvm::PrefixMapper &PrefixMapper)
73
+ : DB(DB), PrefixMapper(PrefixMapper) {}
74
+
75
+ Expected<cas::IncludeTreeRoot>
76
+ finishIncludeTree (CompilerInstance &ScanInstance,
77
+ CompilerInvocation &NewInvocation);
78
+
79
+ void enteredInclude (Preprocessor &PP, FileID FID);
80
+
81
+ void exitedInclude (Preprocessor &PP, FileID IncludedBy, FileID Include,
82
+ SourceLocation ExitLoc);
83
+
84
+ void handleHasIncludeCheck (Preprocessor &PP, bool Result);
85
+
86
+ private:
56
87
struct FilePPState {
57
88
SrcMgr::CharacteristicKind FileCharacteristic;
58
89
cas::ObjectRef File;
59
90
SmallVector<std::pair<cas::ObjectRef, uint32_t >, 6 > Includes;
60
91
llvm::SmallBitVector HasIncludeChecks;
61
92
};
62
93
94
+ Expected<cas::ObjectRef> getObjectForFile (Preprocessor &PP, FileID FID);
95
+ Expected<cas::ObjectRef>
96
+ getObjectForFileNonCached (FileManager &FM, const SrcMgr::FileInfo &FI);
97
+ Expected<cas::ObjectRef> getObjectForBuffer (const SrcMgr::FileInfo &FI);
98
+ Expected<cas::ObjectRef> addToFileList (FileManager &FM, const FileEntry *FE);
63
99
Expected<cas::IncludeTree> getCASTreeForFileIncludes (FilePPState &&PPState);
64
-
65
100
Expected<cas::IncludeFile> createIncludeFile (StringRef Filename,
66
101
cas::ObjectRef Contents);
67
102
@@ -75,10 +110,10 @@ class IncludeTreeActionController : public CallbackActionController {
75
110
return *E;
76
111
}
77
112
113
+ private:
78
114
cas::ObjectStore &DB;
79
- CASOptions CASOpts;
80
- DepscanPrefixMapping PrefixMapping;
81
- llvm::PrefixMapper PrefixMapper;
115
+ llvm::PrefixMapper &PrefixMapper;
116
+
82
117
std::optional<cas::ObjectRef> PCHRef;
83
118
bool StartedEnteringIncludes = false ;
84
119
// When a PCH is used this lists the filenames of the included files as they
@@ -87,6 +122,10 @@ class IncludeTreeActionController : public CallbackActionController {
87
122
llvm::BitVector SeenIncludeFiles;
88
123
SmallVector<cas::IncludeFileList::FileEntry> IncludedFiles;
89
124
std::optional<cas::ObjectRef> PredefinesBufferRef;
125
+ std::optional<cas::ObjectRef> ModuleIncludesBufferRef;
126
+ std::optional<cas::ObjectRef> ModuleMapFileRef;
127
+ // / When the builder is created from an existing tree, the main include tree.
128
+ std::optional<cas::ObjectRef> MainIncludeTreeRef;
90
129
SmallVector<FilePPState> IncludeStack;
91
130
llvm::DenseMap<const FileEntry *, std::optional<cas::ObjectRef>>
92
131
ObjectForFile;
@@ -153,6 +192,13 @@ void dependencies::addReversePrefixMappingFileSystem(
153
192
ScanInstance.getFileManager ().setVirtualFileSystem (std::move (FS));
154
193
}
155
194
195
+ Expected<cas::IncludeTreeRoot> IncludeTreeActionController::getIncludeTree () {
196
+ if (IncludeTreeResult)
197
+ return *IncludeTreeResult;
198
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
199
+ " failed to produce include-tree" );
200
+ }
201
+
156
202
Error IncludeTreeActionController::initialize (
157
203
CompilerInstance &ScanInstance, CompilerInvocation &NewInvocation) {
158
204
if (Error E =
@@ -185,10 +231,50 @@ Error IncludeTreeActionController::initialize(
185
231
186
232
CASOpts = ScanInstance.getCASOpts ();
187
233
234
+ BuilderStack.push_back (
235
+ std::make_unique<IncludeTreeBuilder>(DB, PrefixMapper));
236
+
188
237
return Error::success ();
189
238
}
190
239
191
240
void IncludeTreeActionController::enteredInclude (Preprocessor &PP, FileID FID) {
241
+ current ().enteredInclude (PP, FID);
242
+ }
243
+
244
+ void IncludeTreeActionController::exitedInclude (Preprocessor &PP,
245
+ FileID IncludedBy,
246
+ FileID Include,
247
+ SourceLocation ExitLoc) {
248
+ current ().exitedInclude (PP, IncludedBy, Include, ExitLoc);
249
+ }
250
+
251
+ void IncludeTreeActionController::handleHasIncludeCheck (Preprocessor &PP,
252
+ bool Result) {
253
+ current ().handleHasIncludeCheck (PP, Result);
254
+ }
255
+
256
+ Error IncludeTreeActionController::finalize (CompilerInstance &ScanInstance,
257
+ CompilerInvocation &NewInvocation) {
258
+ assert (!IncludeTreeResult);
259
+ assert (BuilderStack.size () == 1 );
260
+ auto Builder = BuilderStack.pop_back_val ();
261
+ Error E = Builder->finishIncludeTree (ScanInstance, NewInvocation)
262
+ .moveInto (IncludeTreeResult);
263
+ if (E)
264
+ return E;
265
+
266
+ configureInvocationForCaching (NewInvocation, CASOpts,
267
+ IncludeTreeResult->getID ().toString (),
268
+ // FIXME: working dir?
269
+ /* CASFSWorkingDir=*/ " " ,
270
+ /* ProduceIncludeTree=*/ true );
271
+
272
+ DepscanPrefixMapping::remapInvocationPaths (NewInvocation, PrefixMapper);
273
+
274
+ return Error::success ();
275
+ }
276
+
277
+ void IncludeTreeBuilder::enteredInclude (Preprocessor &PP, FileID FID) {
192
278
if (hasErrorOccurred ())
193
279
return ;
194
280
@@ -213,10 +299,8 @@ void IncludeTreeActionController::enteredInclude(Preprocessor &PP, FileID FID) {
213
299
IncludeStack.push_back ({FI.getFileCharacteristic (), *FileRef, {}, {}});
214
300
}
215
301
216
- void IncludeTreeActionController::exitedInclude (Preprocessor &PP,
217
- FileID IncludedBy,
218
- FileID Include,
219
- SourceLocation ExitLoc) {
302
+ void IncludeTreeBuilder::exitedInclude (Preprocessor &PP, FileID IncludedBy,
303
+ FileID Include, SourceLocation ExitLoc) {
220
304
if (hasErrorOccurred ())
221
305
return ;
222
306
@@ -232,16 +316,19 @@ void IncludeTreeActionController::exitedInclude(Preprocessor &PP,
232
316
{IncludeTree->getRef (), LocInfo.second });
233
317
}
234
318
235
- void IncludeTreeActionController::handleHasIncludeCheck (Preprocessor &PP,
236
- bool Result) {
319
+ void IncludeTreeBuilder::handleHasIncludeCheck (Preprocessor &PP, bool Result) {
237
320
if (hasErrorOccurred ())
238
321
return ;
239
322
240
323
IncludeStack.back ().HasIncludeChecks .push_back (Result);
241
324
}
242
325
243
- Error IncludeTreeActionController::finalize (CompilerInstance &ScanInstance,
244
- CompilerInvocation &NewInvocation) {
326
+ Expected<cas::IncludeTreeRoot>
327
+ IncludeTreeBuilder::finishIncludeTree (CompilerInstance &ScanInstance,
328
+ CompilerInvocation &NewInvocation) {
329
+ if (ErrorToReport)
330
+ return std::move (*ErrorToReport);
331
+
245
332
FileManager &FM = ScanInstance.getFileManager ();
246
333
247
334
auto addFile = [&](StringRef FilePath,
@@ -258,21 +345,21 @@ Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
258
345
259
346
for (StringRef FilePath : NewInvocation.getLangOpts ()->NoSanitizeFiles ) {
260
347
if (Error E = addFile (FilePath))
261
- return E ;
348
+ return std::move (E) ;
262
349
}
263
350
// Add profile files.
264
351
// FIXME: Do not have the logic here to determine which path should be set
265
352
// but ideally only the path needed for the compilation is set and we already
266
353
// checked the file needed exists. Just try load and ignore errors.
267
354
if (Error E = addFile (NewInvocation.getCodeGenOpts ().ProfileInstrumentUsePath ,
268
355
/* IgnoreFileError=*/ true ))
269
- return E ;
356
+ return std::move (E) ;
270
357
if (Error E = addFile (NewInvocation.getCodeGenOpts ().SampleProfileFile ,
271
358
/* IgnoreFileError=*/ true ))
272
- return E ;
359
+ return std::move (E) ;
273
360
if (Error E = addFile (NewInvocation.getCodeGenOpts ().ProfileRemappingFile ,
274
361
/* IgnoreFileError=*/ true ))
275
- return E ;
362
+ return std::move (E) ;
276
363
277
364
StringRef Sysroot = NewInvocation.getHeaderSearchOpts ().Sysroot ;
278
365
if (!Sysroot.empty ()) {
@@ -281,7 +368,7 @@ Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
281
368
llvm::SmallString<256 > FilePath = Sysroot;
282
369
llvm::sys::path::append (FilePath, " SDKSettings.json" );
283
370
if (Error E = addFile (FilePath, /* IgnoreFileError*/ true ))
284
- return E ;
371
+ return std::move (E) ;
285
372
}
286
373
287
374
auto FinishIncludeTree = [&]() -> Error {
@@ -320,24 +407,26 @@ Error IncludeTreeActionController::finalize(CompilerInstance &ScanInstance,
320
407
};
321
408
322
409
if (Error E = FinishIncludeTree ())
323
- return E;
324
-
325
- auto IncludeTreeRoot = getIncludeTree ();
326
- if (!IncludeTreeRoot)
327
- return IncludeTreeRoot.takeError ();
410
+ return std::move (E);
328
411
329
- configureInvocationForCaching (NewInvocation, CASOpts,
330
- IncludeTreeRoot->getID ().toString (),
331
- /* CASFSWorkingDir=*/ " " ,
332
- /* ProduceIncludeTree=*/ true );
412
+ if (ErrorToReport)
413
+ return std::move (*ErrorToReport);
333
414
334
- DepscanPrefixMapping::remapInvocationPaths (NewInvocation, PrefixMapper);
415
+ assert (IncludeStack.size () == 1 );
416
+ Expected<cas::IncludeTree> MainIncludeTree =
417
+ getCASTreeForFileIncludes (IncludeStack.pop_back_val ());
418
+ if (!MainIncludeTree)
419
+ return MainIncludeTree.takeError ();
420
+ auto FileList = cas::IncludeFileList::create (DB, IncludedFiles);
421
+ if (!FileList)
422
+ return FileList.takeError ();
335
423
336
- return Error::success ();
424
+ return cas::IncludeTreeRoot::create (DB, MainIncludeTree->getRef (),
425
+ FileList->getRef (), PCHRef);
337
426
}
338
427
339
- Expected<cas::ObjectRef>
340
- IncludeTreeActionController::getObjectForFile (Preprocessor &PP, FileID FID) {
428
+ Expected<cas::ObjectRef> IncludeTreeBuilder::getObjectForFile (Preprocessor &PP,
429
+ FileID FID) {
341
430
SourceManager &SM = PP.getSourceManager ();
342
431
const SrcMgr::FileInfo &FI = SM.getSLocEntry (FID).getFile ();
343
432
if (PP.getPredefinesFileID () == FID) {
@@ -360,8 +449,9 @@ IncludeTreeActionController::getObjectForFile(Preprocessor &PP, FileID FID) {
360
449
return *FileRef;
361
450
}
362
451
363
- Expected<cas::ObjectRef> IncludeTreeActionController::getObjectForFileNonCached (
364
- FileManager &FM, const SrcMgr::FileInfo &FI) {
452
+ Expected<cas::ObjectRef>
453
+ IncludeTreeBuilder::getObjectForFileNonCached (FileManager &FM,
454
+ const SrcMgr::FileInfo &FI) {
365
455
const FileEntry *FE = FI.getContentCache ().OrigEntry ;
366
456
assert (FE);
367
457
@@ -374,7 +464,7 @@ Expected<cas::ObjectRef> IncludeTreeActionController::getObjectForFileNonCached(
374
464
}
375
465
376
466
Expected<cas::ObjectRef>
377
- IncludeTreeActionController ::getObjectForBuffer (const SrcMgr::FileInfo &FI) {
467
+ IncludeTreeBuilder ::getObjectForBuffer (const SrcMgr::FileInfo &FI) {
378
468
// This is a non-file buffer, like the predefines.
379
469
auto Ref = DB.storeFromString (
380
470
{}, FI.getContentCache ().getBufferIfLoaded ()->getBuffer ());
@@ -387,8 +477,7 @@ IncludeTreeActionController::getObjectForBuffer(const SrcMgr::FileInfo &FI) {
387
477
}
388
478
389
479
Expected<cas::ObjectRef>
390
- IncludeTreeActionController::addToFileList (FileManager &FM,
391
- const FileEntry *FE) {
480
+ IncludeTreeBuilder::addToFileList (FileManager &FM, const FileEntry *FE) {
392
481
StringRef Filename = FE->getName ();
393
482
llvm::ErrorOr<std::optional<cas::ObjectRef>> CASContents =
394
483
FM.getObjectRefForFileContent (Filename);
@@ -421,14 +510,14 @@ IncludeTreeActionController::addToFileList(FileManager &FM,
421
510
}
422
511
423
512
Expected<cas::IncludeTree>
424
- IncludeTreeActionController ::getCASTreeForFileIncludes (FilePPState &&PPState) {
513
+ IncludeTreeBuilder ::getCASTreeForFileIncludes (FilePPState &&PPState) {
425
514
return cas::IncludeTree::create (DB, PPState.FileCharacteristic , PPState.File ,
426
515
PPState.Includes , PPState.HasIncludeChecks );
427
516
}
428
517
429
518
Expected<cas::IncludeFile>
430
- IncludeTreeActionController ::createIncludeFile (StringRef Filename,
431
- cas::ObjectRef Contents) {
519
+ IncludeTreeBuilder ::createIncludeFile (StringRef Filename,
520
+ cas::ObjectRef Contents) {
432
521
SmallString<256 > MappedPath;
433
522
if (!PrefixMapper.empty ()) {
434
523
PrefixMapper.map (Filename, MappedPath);
@@ -437,23 +526,6 @@ IncludeTreeActionController::createIncludeFile(StringRef Filename,
437
526
return cas::IncludeFile::create (DB, Filename, std::move (Contents));
438
527
}
439
528
440
- Expected<cas::IncludeTreeRoot> IncludeTreeActionController::getIncludeTree () {
441
- if (ErrorToReport)
442
- return std::move (*ErrorToReport);
443
-
444
- assert (IncludeStack.size () == 1 );
445
- Expected<cas::IncludeTree> MainIncludeTree =
446
- getCASTreeForFileIncludes (IncludeStack.pop_back_val ());
447
- if (!MainIncludeTree)
448
- return MainIncludeTree.takeError ();
449
- auto FileList = cas::IncludeFileList::create (DB, IncludedFiles);
450
- if (!FileList)
451
- return FileList.takeError ();
452
-
453
- return cas::IncludeTreeRoot::create (DB, MainIncludeTree->getRef (),
454
- FileList->getRef (), PCHRef);
455
- }
456
-
457
529
std::unique_ptr<DependencyActionController>
458
530
dependencies::createIncludeTreeActionController (
459
531
cas::ObjectStore &DB, DepscanPrefixMapping PrefixMapping) {
0 commit comments