@@ -95,9 +95,47 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
95
95
}
96
96
};
97
97
98
+ struct ModuleFile ;
99
+
100
+ // ReusablePrerequisiteModules - stands for PrerequisiteModules for which all
101
+ // the required modules are built successfully. All the module files
102
+ // are owned by the modules builder.
103
+ class ReusablePrerequisiteModules : public PrerequisiteModules {
104
+ public:
105
+ ReusablePrerequisiteModules () = default ;
106
+
107
+ ReusablePrerequisiteModules (const ReusablePrerequisiteModules &Other) =
108
+ default ;
109
+ ReusablePrerequisiteModules &
110
+ operator =(const ReusablePrerequisiteModules &) = default ;
111
+ ReusablePrerequisiteModules (ReusablePrerequisiteModules &&) = delete ;
112
+ ReusablePrerequisiteModules
113
+ operator =(ReusablePrerequisiteModules &&) = delete ;
114
+
115
+ ~ReusablePrerequisiteModules () override = default ;
116
+
117
+ void adjustHeaderSearchOptions (HeaderSearchOptions &Options) const override ;
118
+
119
+ bool canReuse (const CompilerInvocation &CI,
120
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) const override ;
121
+
122
+ bool isModuleUnitBuilt (llvm::StringRef ModuleName) const {
123
+ return BuiltModuleNames.contains (ModuleName);
124
+ }
125
+
126
+ void addModuleFile (std::shared_ptr<const ModuleFile> ModuleFile);
127
+
128
+ private:
129
+ llvm::SmallVector<std::shared_ptr<const ModuleFile>, 8 > RequiredModules;
130
+ // A helper class to speedup the query if a module is built.
131
+ llvm::StringSet<> BuiltModuleNames;
132
+ };
133
+
98
134
struct ModuleFile {
99
- ModuleFile (StringRef ModuleName, PathRef ModuleFilePath)
100
- : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
135
+ ModuleFile (StringRef ModuleName, PathRef ModuleFilePath,
136
+ const ReusablePrerequisiteModules &RequiredModuleFiles)
137
+ : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()),
138
+ RequiredModuleFiles (RequiredModuleFiles) {}
101
139
102
140
ModuleFile () = delete;
103
141
@@ -133,8 +171,27 @@ struct ModuleFile {
133
171
private:
134
172
std::string ModuleName;
135
173
std::string ModuleFilePath;
174
+
175
+ // The required module files. We need to share the ownership for required
176
+ // module files.
177
+ ReusablePrerequisiteModules RequiredModuleFiles;
136
178
};
137
179
180
+ void ReusablePrerequisiteModules::adjustHeaderSearchOptions (
181
+ HeaderSearchOptions &Options) const {
182
+ // Appending all built module files.
183
+ for (const auto &RequiredModule : RequiredModules)
184
+ Options.PrebuiltModuleFiles .insert_or_assign (
185
+ RequiredModule->getModuleName ().str (),
186
+ RequiredModule->getModuleFilePath ().str ());
187
+ }
188
+
189
+ void ReusablePrerequisiteModules::addModuleFile (
190
+ std::shared_ptr<const ModuleFile> ModuleFile) {
191
+ BuiltModuleNames.insert (ModuleFile->getModuleName ());
192
+ RequiredModules.emplace_back (std::move (ModuleFile));
193
+ }
194
+
138
195
bool IsModuleFileUpToDate (PathRef ModuleFilePath,
139
196
const PrerequisiteModules &RequisiteModules,
140
197
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
@@ -199,48 +256,6 @@ bool IsModuleFilesUpToDate(
199
256
});
200
257
}
201
258
202
- // ReusablePrerequisiteModules - stands for PrerequisiteModules for which all
203
- // the required modules are built successfully. All the module files
204
- // are owned by the modules builder.
205
- class ReusablePrerequisiteModules : public PrerequisiteModules {
206
- public:
207
- ReusablePrerequisiteModules () = default ;
208
-
209
- ReusablePrerequisiteModules (const ReusablePrerequisiteModules &) = delete ;
210
- ReusablePrerequisiteModules
211
- operator =(const ReusablePrerequisiteModules &) = delete ;
212
- ReusablePrerequisiteModules (ReusablePrerequisiteModules &&) = delete ;
213
- ReusablePrerequisiteModules
214
- operator =(ReusablePrerequisiteModules &&) = delete ;
215
-
216
- ~ReusablePrerequisiteModules () override = default ;
217
-
218
- void adjustHeaderSearchOptions (HeaderSearchOptions &Options) const override {
219
- // Appending all built module files.
220
- for (auto &RequiredModule : RequiredModules)
221
- Options.PrebuiltModuleFiles .insert_or_assign (
222
- RequiredModule->getModuleName ().str (),
223
- RequiredModule->getModuleFilePath ().str ());
224
- }
225
-
226
- bool canReuse (const CompilerInvocation &CI,
227
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) const override ;
228
-
229
- bool isModuleUnitBuilt (llvm::StringRef ModuleName) const {
230
- return BuiltModuleNames.contains (ModuleName);
231
- }
232
-
233
- void addModuleFile (std::shared_ptr<ModuleFile> BMI) {
234
- BuiltModuleNames.insert (BMI->getModuleName ());
235
- RequiredModules.emplace_back (std::move (BMI));
236
- }
237
-
238
- private:
239
- llvm::SmallVector<std::shared_ptr<ModuleFile>, 8 > RequiredModules;
240
- // A helper class to speedup the query if a module is built.
241
- llvm::StringSet<> BuiltModuleNames;
242
- };
243
-
244
259
// / Build a module file for module with `ModuleName`. The information of built
245
260
// / module file are stored in \param BuiltModuleFiles.
246
261
llvm::Expected<ModuleFile>
@@ -294,7 +309,7 @@ buildModuleFile(llvm::StringRef ModuleName, PathRef ModuleUnitFileName,
294
309
if (Clang->getDiagnostics ().hasErrorOccurred ())
295
310
return llvm::createStringError (" Compilation failed" );
296
311
297
- return ModuleFile{ModuleName, Inputs.CompileCommand .Output };
312
+ return ModuleFile{ModuleName, Inputs.CompileCommand .Output , BuiltModuleFiles };
298
313
}
299
314
300
315
bool ReusablePrerequisiteModules::canReuse (
@@ -319,30 +334,32 @@ class ModuleFileCache {
319
334
ReusablePrerequisiteModules &RequiredModules);
320
335
const GlobalCompilationDatabase &getCDB () const { return CDB; }
321
336
322
- std::shared_ptr<ModuleFile>
337
+ std::shared_ptr<const ModuleFile>
323
338
getValidModuleFile (StringRef ModuleName, ProjectModules &MDB,
324
339
const ThreadsafeFS &TFS,
325
340
PrerequisiteModules &BuiltModuleFiles);
326
341
327
- void add (StringRef ModuleName, std::shared_ptr<ModuleFile> ModuleFile) {
328
- std::lock_guard<std::mutex> _ (ModuleFilesMutex);
342
+ void add (StringRef ModuleName, std::shared_ptr<const ModuleFile> ModuleFile) {
343
+ std::lock_guard<std::mutex> Lock (ModuleFilesMutex);
329
344
330
345
ModuleFiles.insert_or_assign (ModuleName, ModuleFile);
331
346
}
332
347
333
348
private:
334
349
const GlobalCompilationDatabase &CDB;
335
350
336
- llvm::StringMap<std::shared_ptr< ModuleFile>> ModuleFiles;
351
+ llvm::StringMap<std::weak_ptr< const ModuleFile>> ModuleFiles;
337
352
// Mutex to guard accesses to ModuleFiles.
338
353
std::mutex ModuleFilesMutex;
339
354
};
340
355
341
356
// / Collect the directly and indirectly required module names for \param
342
357
// / ModuleName. The \param ModuleName is guaranteed to be the first element in
343
358
// / \param ModuleNames.
344
- void getAllRequiredModules (ProjectModules &MDB, StringRef ModuleName,
345
- llvm::SmallVector<StringRef> &ModuleNames) {
359
+ llvm::SmallVector<StringRef> getAllRequiredModules (ProjectModules &MDB,
360
+ StringRef ModuleName) {
361
+ llvm::SmallVector<StringRef> ModuleNames;
362
+
346
363
std::queue<StringRef> Worklist;
347
364
llvm::StringSet<> ModuleNamesSet;
348
365
Worklist.push (ModuleName);
@@ -361,46 +378,60 @@ void getAllRequiredModules(ProjectModules &MDB, StringRef ModuleName,
361
378
if (!ModuleNamesSet.contains (RequiredModuleName))
362
379
Worklist.push (RequiredModuleName);
363
380
}
381
+
382
+ return ModuleNames;
364
383
}
365
384
366
- std::shared_ptr<ModuleFile>
385
+ std::shared_ptr<const ModuleFile>
367
386
ModuleFileCache::getValidModuleFile (StringRef ModuleName, ProjectModules &MDB,
368
387
const ThreadsafeFS &TFS,
369
388
PrerequisiteModules &BuiltModuleFiles) {
370
389
{
371
- std::lock_guard<std::mutex> _ (ModuleFilesMutex);
390
+ std::lock_guard<std::mutex> Lock (ModuleFilesMutex);
391
+
392
+ auto Iter = ModuleFiles.find (ModuleName);
393
+ if (Iter == ModuleFiles.end ())
394
+ return nullptr ;
372
395
373
- if (ModuleFiles.find (ModuleName) == ModuleFiles.end ())
396
+ if (Iter->second .expired ()) {
397
+ ModuleFiles.erase (Iter);
374
398
return nullptr ;
399
+ }
375
400
}
376
401
377
- llvm::SmallVector<StringRef> ModuleNames;
378
- getAllRequiredModules (MDB, ModuleName, ModuleNames );
402
+ llvm::SmallVector<StringRef> ModuleNames =
403
+ getAllRequiredModules (MDB, ModuleName);
379
404
380
- llvm::SmallVector<std::shared_ptr<ModuleFile>> RequiredModuleFiles;
405
+ llvm::SmallVector<std::shared_ptr<const ModuleFile>> RequiredModuleFiles;
381
406
382
407
{
383
- std::lock_guard<std::mutex> _ (ModuleFilesMutex);
408
+ std::lock_guard<std::mutex> Lock (ModuleFilesMutex);
384
409
385
410
for (StringRef ModuleName : ModuleNames) {
386
411
auto Iter = ModuleFiles.find (ModuleName);
387
412
if (Iter == ModuleFiles.end ())
388
413
return nullptr ;
389
414
390
- RequiredModuleFiles.push_back (Iter->second );
415
+ if (Iter->second .expired ()) {
416
+ ModuleFiles.erase (Iter);
417
+ return nullptr ;
418
+ }
419
+
420
+ RequiredModuleFiles.push_back (Iter->second .lock ());
391
421
}
392
422
}
393
423
394
- if (RequiredModuleFiles.empty ())
395
- return nullptr ;
424
+ assert (!RequiredModuleFiles.empty ());
396
425
397
- if (llvm::all_of (RequiredModuleFiles, [&](auto MF) {
398
- return IsModuleFileUpToDate (MF->getModuleFilePath (), BuiltModuleFiles,
399
- TFS.view (std::nullopt));
400
- }))
401
- return RequiredModuleFiles[0 ];
426
+ if (llvm::any_of (RequiredModuleFiles,
427
+ [&](std::shared_ptr<const ModuleFile> MF) {
428
+ return !IsModuleFileUpToDate (MF->getModuleFilePath (),
429
+ BuiltModuleFiles,
430
+ TFS.view (std::nullopt));
431
+ }))
432
+ return nullptr ;
402
433
403
- return nullptr ;
434
+ return RequiredModuleFiles[ 0 ] ;
404
435
}
405
436
} // namespace
406
437
@@ -443,7 +474,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
443
474
return llvm::createStringError (
444
475
llvm::formatv (" Failed to build module {0}" , RequiredModuleName));
445
476
446
- if (std::shared_ptr<ModuleFile> Cached =
477
+ if (std::shared_ptr<const ModuleFile> Cached =
447
478
Cache.getValidModuleFile (ModuleName, MDB, TFS, BuiltModuleFiles)) {
448
479
log (" Reusing module {0} from {1}" , ModuleName, Cached->getModuleFilePath ());
449
480
BuiltModuleFiles.addModuleFile (Cached);
@@ -462,7 +493,7 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
462
493
return Err;
463
494
464
495
log (" Built module {0} to {1}" , ModuleName, MF->getModuleFilePath ());
465
- auto BuiltModuleFile = std::make_shared<ModuleFile>(std::move (*MF));
496
+ auto BuiltModuleFile = std::make_shared<const ModuleFile>(std::move (*MF));
466
497
Cache.add (ModuleName, BuiltModuleFile);
467
498
BuiltModuleFiles.addModuleFile (std::move (BuiltModuleFile));
468
499
0 commit comments