Skip to content

Commit c84d8e8

Browse files
authored
[clang][modules] Introduce new ModuleCache interface (#131193)
This PR adds new `ModuleCache` interface to Clang's implicitly-built modules machinery. The main motivation for this change is to create a second implementation that uses a more efficient kind of `llvm::AdvisoryLock` during dependency scanning. In addition to the lock abstraction, the `ModuleCache` interface also manages the existing `InMemoryModuleCache` instance. I found that compared to keeping these separate/independent, the code is a bit simpler now, since these are two tightly coupled concepts. I can envision a more efficient implementation of the `InMemoryModuleCache` for the single-process case too, which will be much easier to implement with the current setup. This is not intended to be a functional change.
1 parent d0a0de5 commit c84d8e8

File tree

18 files changed

+211
-113
lines changed

18 files changed

+211
-113
lines changed

clang-tools-extra/clangd/ModulesBuilder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "clang/Frontend/FrontendAction.h"
1313
#include "clang/Frontend/FrontendActions.h"
1414
#include "clang/Serialization/ASTReader.h"
15-
#include "clang/Serialization/InMemoryModuleCache.h"
15+
#include "clang/Serialization/ModuleCache.h"
1616
#include "llvm/ADT/ScopeExit.h"
1717
#include <queue>
1818

@@ -206,9 +206,9 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath,
206206
Preprocessor PP(std::make_shared<PreprocessorOptions>(), *Diags, LangOpts,
207207
SourceMgr, HeaderInfo, ModuleLoader);
208208

209-
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache = new InMemoryModuleCache;
209+
IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();
210210
PCHContainerOperations PCHOperations;
211-
ASTReader Reader(PP, *ModuleCache, /*ASTContext=*/nullptr,
211+
ASTReader Reader(PP, *ModCache, /*ASTContext=*/nullptr,
212212
PCHOperations.getRawReader(), {});
213213

214214
// We don't need any listener here. By default it will use a validator

clang/include/clang/Frontend/ASTUnit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class FileManager;
7070
class FrontendAction;
7171
class HeaderSearch;
7272
class InputKind;
73-
class InMemoryModuleCache;
73+
class ModuleCache;
7474
class PCHContainerOperations;
7575
class PCHContainerReader;
7676
class Preprocessor;
@@ -110,7 +110,7 @@ class ASTUnit {
110110
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
111111
IntrusiveRefCntPtr<FileManager> FileMgr;
112112
IntrusiveRefCntPtr<SourceManager> SourceMgr;
113-
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;
113+
IntrusiveRefCntPtr<ModuleCache> ModCache;
114114
std::unique_ptr<HeaderSearch> HeaderInfo;
115115
IntrusiveRefCntPtr<TargetInfo> Target;
116116
std::shared_ptr<Preprocessor> PP;

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ class DiagnosticsEngine;
5151
class DiagnosticConsumer;
5252
class FileManager;
5353
class FrontendAction;
54-
class InMemoryModuleCache;
5554
class Module;
55+
class ModuleCache;
5656
class Preprocessor;
5757
class Sema;
5858
class SourceManager;
@@ -97,7 +97,7 @@ class CompilerInstance : public ModuleLoader {
9797
IntrusiveRefCntPtr<SourceManager> SourceMgr;
9898

9999
/// The cache of PCM files.
100-
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;
100+
IntrusiveRefCntPtr<ModuleCache> ModCache;
101101

102102
/// The preprocessor.
103103
std::shared_ptr<Preprocessor> PP;
@@ -209,7 +209,7 @@ class CompilerInstance : public ModuleLoader {
209209
explicit CompilerInstance(
210210
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
211211
std::make_shared<PCHContainerOperations>(),
212-
InMemoryModuleCache *SharedModuleCache = nullptr);
212+
ModuleCache *ModCache = nullptr);
213213
~CompilerInstance() override;
214214

215215
/// @name High-Level Operations
@@ -746,9 +746,8 @@ class CompilerInstance : public ModuleLoader {
746746
static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
747747
StringRef Path, StringRef Sysroot,
748748
DisableValidationForModuleKind DisableValidation,
749-
bool AllowPCHWithCompilerErrors, Preprocessor &PP,
750-
InMemoryModuleCache &ModuleCache, ASTContext &Context,
751-
const PCHContainerReader &PCHContainerRdr,
749+
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache,
750+
ASTContext &Context, const PCHContainerReader &PCHContainerRdr,
752751
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
753752
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
754753
void *DeserializationListener, bool OwnDeserializationListener,
@@ -896,7 +895,7 @@ class CompilerInstance : public ModuleLoader {
896895

897896
void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS);
898897

899-
InMemoryModuleCache &getModuleCache() const { return *ModuleCache; }
898+
ModuleCache &getModuleCache() const { return *ModCache; }
900899
};
901900

902901
} // end namespace clang

clang/include/clang/Serialization/ASTReader.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct HeaderFileInfo;
8989
class HeaderSearchOptions;
9090
class LangOptions;
9191
class MacroInfo;
92-
class InMemoryModuleCache;
92+
class ModuleCache;
9393
class NamedDecl;
9494
class NamespaceDecl;
9595
class ObjCCategoryDecl;
@@ -1742,8 +1742,8 @@ class ASTReader
17421742
///
17431743
/// \param ReadTimer If non-null, a timer used to track the time spent
17441744
/// deserializing.
1745-
ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
1746-
ASTContext *Context, const PCHContainerReader &PCHContainerRdr,
1745+
ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context,
1746+
const PCHContainerReader &PCHContainerRdr,
17471747
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
17481748
StringRef isysroot = "",
17491749
DisableValidationForModuleKind DisableValidationKind =
@@ -1954,8 +1954,7 @@ class ASTReader
19541954
///
19551955
/// \returns true if an error occurred, false otherwise.
19561956
static bool readASTFileControlBlock(
1957-
StringRef Filename, FileManager &FileMgr,
1958-
const InMemoryModuleCache &ModuleCache,
1957+
StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
19591958
const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
19601959
ASTReaderListener &Listener, bool ValidateDiagnosticOptions,
19611960
unsigned ClientLoadCapabilities = ARR_ConfigurationMismatch |
@@ -1964,7 +1963,7 @@ class ASTReader
19641963
/// Determine whether the given AST file is acceptable to load into a
19651964
/// translation unit with the given language and target options.
19661965
static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
1967-
const InMemoryModuleCache &ModuleCache,
1966+
const ModuleCache &ModCache,
19681967
const PCHContainerReader &PCHContainerRdr,
19691968
const LangOptions &LangOpts,
19701969
const TargetOptions &TargetOpts,

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class LangOptions;
6060
class MacroDefinitionRecord;
6161
class MacroInfo;
6262
class Module;
63-
class InMemoryModuleCache;
63+
class ModuleCache;
6464
class ModuleFileExtension;
6565
class ModuleFileExtensionWriter;
6666
class NamedDecl;
@@ -117,7 +117,7 @@ class ASTWriter : public ASTDeserializationListener,
117117
const SmallVectorImpl<char> &Buffer;
118118

119119
/// The PCM manager which manages memory buffers for pcm files.
120-
InMemoryModuleCache &ModuleCache;
120+
ModuleCache &ModCache;
121121

122122
/// The preprocessor we're writing.
123123
Preprocessor *PP = nullptr;
@@ -682,7 +682,7 @@ class ASTWriter : public ASTDeserializationListener,
682682
/// Create a new precompiled header writer that outputs to
683683
/// the given bitstream.
684684
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
685-
InMemoryModuleCache &ModuleCache,
685+
ModuleCache &ModCache,
686686
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
687687
bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
688688
bool GeneratingReducedBMI = false);
@@ -986,9 +986,8 @@ class PCHGenerator : public SemaConsumer {
986986
virtual Module *getEmittingModule(ASTContext &Ctx);
987987

988988
public:
989-
PCHGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
990-
StringRef OutputFile, StringRef isysroot,
991-
std::shared_ptr<PCHBuffer> Buffer,
989+
PCHGenerator(Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile,
990+
StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
992991
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
993992
bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
994993
bool BuildingImplicitModule = false,
@@ -1010,14 +1009,14 @@ class CXX20ModulesGenerator : public PCHGenerator {
10101009
protected:
10111010
virtual Module *getEmittingModule(ASTContext &Ctx) override;
10121011

1013-
CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
1012+
CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
10141013
StringRef OutputFile, bool GeneratingReducedBMI,
10151014
bool AllowASTWithErrors);
10161015

10171016
public:
1018-
CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
1017+
CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
10191018
StringRef OutputFile, bool AllowASTWithErrors = false)
1020-
: CXX20ModulesGenerator(PP, ModuleCache, OutputFile,
1019+
: CXX20ModulesGenerator(PP, ModCache, OutputFile,
10211020
/*GeneratingReducedBMI=*/false,
10221021
AllowASTWithErrors) {}
10231022

@@ -1028,9 +1027,9 @@ class ReducedBMIGenerator : public CXX20ModulesGenerator {
10281027
void anchor() override;
10291028

10301029
public:
1031-
ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
1030+
ReducedBMIGenerator(Preprocessor &PP, ModuleCache &ModCache,
10321031
StringRef OutputFile, bool AllowASTWithErrors = false)
1033-
: CXX20ModulesGenerator(PP, ModuleCache, OutputFile,
1032+
: CXX20ModulesGenerator(PP, ModCache, OutputFile,
10341033
/*GeneratingReducedBMI=*/true,
10351034
AllowASTWithErrors) {}
10361035
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_SERIALIZATION_MODULECACHE_H
10+
#define LLVM_CLANG_SERIALIZATION_MODULECACHE_H
11+
12+
#include "clang/Basic/LLVM.h"
13+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
14+
15+
namespace llvm {
16+
class AdvisoryLock;
17+
} // namespace llvm
18+
19+
namespace clang {
20+
class InMemoryModuleCache;
21+
22+
/// The module cache used for compiling modules implicitly. This centralizes the
23+
/// operations the compiler might want to perform on the cache.
24+
class ModuleCache : public RefCountedBase<ModuleCache> {
25+
public:
26+
/// May perform any work that only needs to be performed once for multiple
27+
/// calls \c getLock() with the same module filename.
28+
virtual void prepareForGetLock(StringRef ModuleFilename) = 0;
29+
30+
/// Returns lock for the given module file. The lock is initially unlocked.
31+
virtual std::unique_ptr<llvm::AdvisoryLock>
32+
getLock(StringRef ModuleFilename) = 0;
33+
34+
/// Returns this process's view of the module cache.
35+
virtual InMemoryModuleCache &getInMemoryModuleCache() = 0;
36+
virtual const InMemoryModuleCache &getInMemoryModuleCache() const = 0;
37+
38+
// TODO: Virtualize writing/reading PCM files, timestamping, pruning, etc.
39+
40+
virtual ~ModuleCache() = default;
41+
};
42+
43+
/// Creates new \c ModuleCache backed by a file system directory that may be
44+
/// operated on by multiple processes. This instance must be used across all
45+
/// \c CompilerInstance instances participating in building modules for single
46+
/// translation unit in order to share the same \c InMemoryModuleCache.
47+
IntrusiveRefCntPtr<ModuleCache> createCrossProcessModuleCache();
48+
} // namespace clang
49+
50+
#endif

clang/include/clang/Serialization/ModuleManager.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class FileEntry;
3737
class FileManager;
3838
class GlobalModuleIndex;
3939
class HeaderSearch;
40-
class InMemoryModuleCache;
40+
class ModuleCache;
4141
class PCHContainerReader;
4242

4343
namespace serialization {
@@ -65,7 +65,7 @@ class ModuleManager {
6565
FileManager &FileMgr;
6666

6767
/// Cache of PCM files.
68-
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;
68+
IntrusiveRefCntPtr<ModuleCache> ModCache;
6969

7070
/// Knows how to unwrap module containers.
7171
const PCHContainerReader &PCHContainerRdr;
@@ -133,9 +133,9 @@ class ModuleManager {
133133
SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>;
134134
using ModuleOffset = std::pair<uint32_t, StringRef>;
135135

136-
explicit ModuleManager(FileManager &FileMgr, InMemoryModuleCache &ModuleCache,
137-
const PCHContainerReader &PCHContainerRdr,
138-
const HeaderSearch &HeaderSearchInfo);
136+
ModuleManager(FileManager &FileMgr, ModuleCache &ModCache,
137+
const PCHContainerReader &PCHContainerRdr,
138+
const HeaderSearch &HeaderSearchInfo);
139139

140140
/// Forward iterator to traverse all loaded modules.
141141
ModuleIterator begin() { return Chain.begin(); }
@@ -306,7 +306,7 @@ class ModuleManager {
306306
/// View the graphviz representation of the module graph.
307307
void viewGraph();
308308

309-
InMemoryModuleCache &getModuleCache() const { return *ModuleCache; }
309+
ModuleCache &getModuleCache() const { return *ModCache; }
310310
};
311311

312312
} // namespace serialization

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
#include "clang/Serialization/ASTReader.h"
6262
#include "clang/Serialization/ASTWriter.h"
6363
#include "clang/Serialization/ContinuousRangeMap.h"
64-
#include "clang/Serialization/InMemoryModuleCache.h"
64+
#include "clang/Serialization/ModuleCache.h"
6565
#include "clang/Serialization/ModuleFile.h"
6666
#include "clang/Serialization/PCHContainerOperations.h"
6767
#include "llvm/ADT/ArrayRef.h"
@@ -219,8 +219,8 @@ struct ASTUnit::ASTWriterData {
219219
llvm::BitstreamWriter Stream;
220220
ASTWriter Writer;
221221

222-
ASTWriterData(InMemoryModuleCache &ModuleCache)
223-
: Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {}
222+
ASTWriterData(ModuleCache &ModCache)
223+
: Stream(Buffer), Writer(Stream, Buffer, ModCache, {}) {}
224224
};
225225

226226
void ASTUnit::clearFileLevelDecls() {
@@ -829,7 +829,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
829829
AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
830830
AST->getFileManager(),
831831
UserFilesAreVolatile);
832-
AST->ModuleCache = new InMemoryModuleCache;
832+
AST->ModCache = createCrossProcessModuleCache();
833833
AST->HSOpts = HSOpts ? HSOpts : std::make_shared<HeaderSearchOptions>();
834834
AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front());
835835
AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
@@ -861,8 +861,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
861861
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
862862
disableValid = DisableValidationForModuleKind::All;
863863
AST->Reader = new ASTReader(
864-
PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},
865-
/*isysroot=*/"",
864+
PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, {}, /*isysroot=*/"",
866865
/*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);
867866

868867
unsigned Counter = 0;
@@ -1546,7 +1545,7 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
15461545
AST->UserFilesAreVolatile = UserFilesAreVolatile;
15471546
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
15481547
UserFilesAreVolatile);
1549-
AST->ModuleCache = new InMemoryModuleCache;
1548+
AST->ModCache = createCrossProcessModuleCache();
15501549

15511550
return AST;
15521551
}
@@ -1833,7 +1832,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
18331832
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
18341833
AST->StorePreamblesInMemory = StorePreamblesInMemory;
18351834
AST->PreambleStoragePath = PreambleStoragePath;
1836-
AST->ModuleCache = new InMemoryModuleCache;
1835+
AST->ModCache = createCrossProcessModuleCache();
18371836
AST->OnlyLocalDecls = OnlyLocalDecls;
18381837
AST->CaptureDiagnostics = CaptureDiagnostics;
18391838
AST->TUKind = TUKind;
@@ -1844,7 +1843,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
18441843
AST->Invocation = CI;
18451844
AST->SkipFunctionBodies = SkipFunctionBodies;
18461845
if (ForSerialization)
1847-
AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache));
1846+
AST->WriterData.reset(new ASTWriterData(*AST->ModCache));
18481847
// Zero out now to ease cleanup during crash recovery.
18491848
CI = nullptr;
18501849
Diags = nullptr;
@@ -2379,8 +2378,8 @@ bool ASTUnit::serialize(raw_ostream &OS) {
23792378

23802379
SmallString<128> Buffer;
23812380
llvm::BitstreamWriter Stream(Buffer);
2382-
InMemoryModuleCache ModuleCache;
2383-
ASTWriter Writer(Stream, Buffer, ModuleCache, {});
2381+
IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();
2382+
ASTWriter Writer(Stream, Buffer, *ModCache, {});
23842383
return serializeUnit(Writer, Buffer, getSema(), OS);
23852384
}
23862385

0 commit comments

Comments
 (0)