[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.
This commit is contained in:
Jan Svoboda 2025-03-14 11:32:39 -07:00 committed by GitHub
parent d0a0de50f7
commit c84d8e8f1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 211 additions and 113 deletions

View File

@ -12,7 +12,7 @@
#include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendActions.h"
#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/ModuleCache.h"
#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/ScopeExit.h"
#include <queue> #include <queue>
@ -206,9 +206,9 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath,
Preprocessor PP(std::make_shared<PreprocessorOptions>(), *Diags, LangOpts, Preprocessor PP(std::make_shared<PreprocessorOptions>(), *Diags, LangOpts,
SourceMgr, HeaderInfo, ModuleLoader); SourceMgr, HeaderInfo, ModuleLoader);
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache = new InMemoryModuleCache; IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();
PCHContainerOperations PCHOperations; PCHContainerOperations PCHOperations;
ASTReader Reader(PP, *ModuleCache, /*ASTContext=*/nullptr, ASTReader Reader(PP, *ModCache, /*ASTContext=*/nullptr,
PCHOperations.getRawReader(), {}); PCHOperations.getRawReader(), {});
// We don't need any listener here. By default it will use a validator // We don't need any listener here. By default it will use a validator

View File

@ -70,7 +70,7 @@ class FileManager;
class FrontendAction; class FrontendAction;
class HeaderSearch; class HeaderSearch;
class InputKind; class InputKind;
class InMemoryModuleCache; class ModuleCache;
class PCHContainerOperations; class PCHContainerOperations;
class PCHContainerReader; class PCHContainerReader;
class Preprocessor; class Preprocessor;
@ -110,7 +110,7 @@ private:
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
IntrusiveRefCntPtr<FileManager> FileMgr; IntrusiveRefCntPtr<FileManager> FileMgr;
IntrusiveRefCntPtr<SourceManager> SourceMgr; IntrusiveRefCntPtr<SourceManager> SourceMgr;
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache; IntrusiveRefCntPtr<ModuleCache> ModCache;
std::unique_ptr<HeaderSearch> HeaderInfo; std::unique_ptr<HeaderSearch> HeaderInfo;
IntrusiveRefCntPtr<TargetInfo> Target; IntrusiveRefCntPtr<TargetInfo> Target;
std::shared_ptr<Preprocessor> PP; std::shared_ptr<Preprocessor> PP;

View File

@ -51,8 +51,8 @@ class DiagnosticsEngine;
class DiagnosticConsumer; class DiagnosticConsumer;
class FileManager; class FileManager;
class FrontendAction; class FrontendAction;
class InMemoryModuleCache;
class Module; class Module;
class ModuleCache;
class Preprocessor; class Preprocessor;
class Sema; class Sema;
class SourceManager; class SourceManager;
@ -97,7 +97,7 @@ class CompilerInstance : public ModuleLoader {
IntrusiveRefCntPtr<SourceManager> SourceMgr; IntrusiveRefCntPtr<SourceManager> SourceMgr;
/// The cache of PCM files. /// The cache of PCM files.
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache; IntrusiveRefCntPtr<ModuleCache> ModCache;
/// The preprocessor. /// The preprocessor.
std::shared_ptr<Preprocessor> PP; std::shared_ptr<Preprocessor> PP;
@ -209,7 +209,7 @@ public:
explicit CompilerInstance( explicit CompilerInstance(
std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(), std::make_shared<PCHContainerOperations>(),
InMemoryModuleCache *SharedModuleCache = nullptr); ModuleCache *ModCache = nullptr);
~CompilerInstance() override; ~CompilerInstance() override;
/// @name High-Level Operations /// @name High-Level Operations
@ -746,9 +746,8 @@ public:
static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource( static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
StringRef Path, StringRef Sysroot, StringRef Path, StringRef Sysroot,
DisableValidationForModuleKind DisableValidation, DisableValidationForModuleKind DisableValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache,
InMemoryModuleCache &ModuleCache, ASTContext &Context, ASTContext &Context, const PCHContainerReader &PCHContainerRdr,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener, void *DeserializationListener, bool OwnDeserializationListener,
@ -896,7 +895,7 @@ public:
void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS); void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS);
InMemoryModuleCache &getModuleCache() const { return *ModuleCache; } ModuleCache &getModuleCache() const { return *ModCache; }
}; };
} // end namespace clang } // end namespace clang

View File

@ -89,7 +89,7 @@ struct HeaderFileInfo;
class HeaderSearchOptions; class HeaderSearchOptions;
class LangOptions; class LangOptions;
class MacroInfo; class MacroInfo;
class InMemoryModuleCache; class ModuleCache;
class NamedDecl; class NamedDecl;
class NamespaceDecl; class NamespaceDecl;
class ObjCCategoryDecl; class ObjCCategoryDecl;
@ -1742,8 +1742,8 @@ public:
/// ///
/// \param ReadTimer If non-null, a timer used to track the time spent /// \param ReadTimer If non-null, a timer used to track the time spent
/// deserializing. /// deserializing.
ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache, ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context,
ASTContext *Context, const PCHContainerReader &PCHContainerRdr, const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
StringRef isysroot = "", StringRef isysroot = "",
DisableValidationForModuleKind DisableValidationKind = DisableValidationForModuleKind DisableValidationKind =
@ -1954,8 +1954,7 @@ public:
/// ///
/// \returns true if an error occurred, false otherwise. /// \returns true if an error occurred, false otherwise.
static bool readASTFileControlBlock( static bool readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr, StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
const InMemoryModuleCache &ModuleCache,
const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
ASTReaderListener &Listener, bool ValidateDiagnosticOptions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions,
unsigned ClientLoadCapabilities = ARR_ConfigurationMismatch | unsigned ClientLoadCapabilities = ARR_ConfigurationMismatch |
@ -1964,7 +1963,7 @@ public:
/// Determine whether the given AST file is acceptable to load into a /// Determine whether the given AST file is acceptable to load into a
/// translation unit with the given language and target options. /// translation unit with the given language and target options.
static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
const InMemoryModuleCache &ModuleCache, const ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr, const PCHContainerReader &PCHContainerRdr,
const LangOptions &LangOpts, const LangOptions &LangOpts,
const TargetOptions &TargetOpts, const TargetOptions &TargetOpts,

View File

@ -60,7 +60,7 @@ class LangOptions;
class MacroDefinitionRecord; class MacroDefinitionRecord;
class MacroInfo; class MacroInfo;
class Module; class Module;
class InMemoryModuleCache; class ModuleCache;
class ModuleFileExtension; class ModuleFileExtension;
class ModuleFileExtensionWriter; class ModuleFileExtensionWriter;
class NamedDecl; class NamedDecl;
@ -117,7 +117,7 @@ private:
const SmallVectorImpl<char> &Buffer; const SmallVectorImpl<char> &Buffer;
/// The PCM manager which manages memory buffers for pcm files. /// The PCM manager which manages memory buffers for pcm files.
InMemoryModuleCache &ModuleCache; ModuleCache &ModCache;
/// The preprocessor we're writing. /// The preprocessor we're writing.
Preprocessor *PP = nullptr; Preprocessor *PP = nullptr;
@ -682,7 +682,7 @@ public:
/// Create a new precompiled header writer that outputs to /// Create a new precompiled header writer that outputs to
/// the given bitstream. /// the given bitstream.
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
InMemoryModuleCache &ModuleCache, ModuleCache &ModCache,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps = true, bool BuildingImplicitModule = false, bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
bool GeneratingReducedBMI = false); bool GeneratingReducedBMI = false);
@ -986,9 +986,8 @@ protected:
virtual Module *getEmittingModule(ASTContext &Ctx); virtual Module *getEmittingModule(ASTContext &Ctx);
public: public:
PCHGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, PCHGenerator(Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile,
StringRef OutputFile, StringRef isysroot, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors = false, bool IncludeTimestamps = true, bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
bool BuildingImplicitModule = false, bool BuildingImplicitModule = false,
@ -1010,14 +1009,14 @@ class CXX20ModulesGenerator : public PCHGenerator {
protected: protected:
virtual Module *getEmittingModule(ASTContext &Ctx) override; virtual Module *getEmittingModule(ASTContext &Ctx) override;
CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
StringRef OutputFile, bool GeneratingReducedBMI, StringRef OutputFile, bool GeneratingReducedBMI,
bool AllowASTWithErrors); bool AllowASTWithErrors);
public: public:
CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
StringRef OutputFile, bool AllowASTWithErrors = false) StringRef OutputFile, bool AllowASTWithErrors = false)
: CXX20ModulesGenerator(PP, ModuleCache, OutputFile, : CXX20ModulesGenerator(PP, ModCache, OutputFile,
/*GeneratingReducedBMI=*/false, /*GeneratingReducedBMI=*/false,
AllowASTWithErrors) {} AllowASTWithErrors) {}
@ -1028,9 +1027,9 @@ class ReducedBMIGenerator : public CXX20ModulesGenerator {
void anchor() override; void anchor() override;
public: public:
ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache, ReducedBMIGenerator(Preprocessor &PP, ModuleCache &ModCache,
StringRef OutputFile, bool AllowASTWithErrors = false) StringRef OutputFile, bool AllowASTWithErrors = false)
: CXX20ModulesGenerator(PP, ModuleCache, OutputFile, : CXX20ModulesGenerator(PP, ModCache, OutputFile,
/*GeneratingReducedBMI=*/true, /*GeneratingReducedBMI=*/true,
AllowASTWithErrors) {} AllowASTWithErrors) {}
}; };

View File

@ -0,0 +1,50 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SERIALIZATION_MODULECACHE_H
#define LLVM_CLANG_SERIALIZATION_MODULECACHE_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
namespace llvm {
class AdvisoryLock;
} // namespace llvm
namespace clang {
class InMemoryModuleCache;
/// The module cache used for compiling modules implicitly. This centralizes the
/// operations the compiler might want to perform on the cache.
class ModuleCache : public RefCountedBase<ModuleCache> {
public:
/// May perform any work that only needs to be performed once for multiple
/// calls \c getLock() with the same module filename.
virtual void prepareForGetLock(StringRef ModuleFilename) = 0;
/// Returns lock for the given module file. The lock is initially unlocked.
virtual std::unique_ptr<llvm::AdvisoryLock>
getLock(StringRef ModuleFilename) = 0;
/// Returns this process's view of the module cache.
virtual InMemoryModuleCache &getInMemoryModuleCache() = 0;
virtual const InMemoryModuleCache &getInMemoryModuleCache() const = 0;
// TODO: Virtualize writing/reading PCM files, timestamping, pruning, etc.
virtual ~ModuleCache() = default;
};
/// Creates new \c ModuleCache backed by a file system directory that may be
/// operated on by multiple processes. This instance must be used across all
/// \c CompilerInstance instances participating in building modules for single
/// translation unit in order to share the same \c InMemoryModuleCache.
IntrusiveRefCntPtr<ModuleCache> createCrossProcessModuleCache();
} // namespace clang
#endif

View File

@ -37,7 +37,7 @@ class FileEntry;
class FileManager; class FileManager;
class GlobalModuleIndex; class GlobalModuleIndex;
class HeaderSearch; class HeaderSearch;
class InMemoryModuleCache; class ModuleCache;
class PCHContainerReader; class PCHContainerReader;
namespace serialization { namespace serialization {
@ -65,7 +65,7 @@ class ModuleManager {
FileManager &FileMgr; FileManager &FileMgr;
/// Cache of PCM files. /// Cache of PCM files.
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache; IntrusiveRefCntPtr<ModuleCache> ModCache;
/// Knows how to unwrap module containers. /// Knows how to unwrap module containers.
const PCHContainerReader &PCHContainerRdr; const PCHContainerReader &PCHContainerRdr;
@ -133,9 +133,9 @@ public:
SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>; SmallVectorImpl<std::unique_ptr<ModuleFile>>::reverse_iterator>;
using ModuleOffset = std::pair<uint32_t, StringRef>; using ModuleOffset = std::pair<uint32_t, StringRef>;
explicit ModuleManager(FileManager &FileMgr, InMemoryModuleCache &ModuleCache, ModuleManager(FileManager &FileMgr, ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr, const PCHContainerReader &PCHContainerRdr,
const HeaderSearch &HeaderSearchInfo); const HeaderSearch &HeaderSearchInfo);
/// Forward iterator to traverse all loaded modules. /// Forward iterator to traverse all loaded modules.
ModuleIterator begin() { return Chain.begin(); } ModuleIterator begin() { return Chain.begin(); }
@ -306,7 +306,7 @@ public:
/// View the graphviz representation of the module graph. /// View the graphviz representation of the module graph.
void viewGraph(); void viewGraph();
InMemoryModuleCache &getModuleCache() const { return *ModuleCache; } ModuleCache &getModuleCache() const { return *ModCache; }
}; };
} // namespace serialization } // namespace serialization

View File

@ -61,7 +61,7 @@
#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h" #include "clang/Serialization/ASTWriter.h"
#include "clang/Serialization/ContinuousRangeMap.h" #include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/ModuleFile.h" #include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/PCHContainerOperations.h" #include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
@ -219,8 +219,8 @@ struct ASTUnit::ASTWriterData {
llvm::BitstreamWriter Stream; llvm::BitstreamWriter Stream;
ASTWriter Writer; ASTWriter Writer;
ASTWriterData(InMemoryModuleCache &ModuleCache) ASTWriterData(ModuleCache &ModCache)
: Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {} : Stream(Buffer), Writer(Stream, Buffer, ModCache, {}) {}
}; };
void ASTUnit::clearFileLevelDecls() { void ASTUnit::clearFileLevelDecls() {
@ -829,7 +829,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
AST->getFileManager(), AST->getFileManager(),
UserFilesAreVolatile); UserFilesAreVolatile);
AST->ModuleCache = new InMemoryModuleCache; AST->ModCache = createCrossProcessModuleCache();
AST->HSOpts = HSOpts ? HSOpts : std::make_shared<HeaderSearchOptions>(); AST->HSOpts = HSOpts ? HSOpts : std::make_shared<HeaderSearchOptions>();
AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front()); AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormats().front());
AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
@ -861,8 +861,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
disableValid = DisableValidationForModuleKind::All; disableValid = DisableValidationForModuleKind::All;
AST->Reader = new ASTReader( AST->Reader = new ASTReader(
PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {}, PP, *AST->ModCache, AST->Ctx.get(), PCHContainerRdr, {}, /*isysroot=*/"",
/*isysroot=*/"",
/*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors); /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors);
unsigned Counter = 0; unsigned Counter = 0;
@ -1546,7 +1545,7 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
UserFilesAreVolatile); UserFilesAreVolatile);
AST->ModuleCache = new InMemoryModuleCache; AST->ModCache = createCrossProcessModuleCache();
return AST; return AST;
} }
@ -1833,7 +1832,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
AST->StorePreamblesInMemory = StorePreamblesInMemory; AST->StorePreamblesInMemory = StorePreamblesInMemory;
AST->PreambleStoragePath = PreambleStoragePath; AST->PreambleStoragePath = PreambleStoragePath;
AST->ModuleCache = new InMemoryModuleCache; AST->ModCache = createCrossProcessModuleCache();
AST->OnlyLocalDecls = OnlyLocalDecls; AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics; AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind; AST->TUKind = TUKind;
@ -1844,7 +1843,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
AST->Invocation = CI; AST->Invocation = CI;
AST->SkipFunctionBodies = SkipFunctionBodies; AST->SkipFunctionBodies = SkipFunctionBodies;
if (ForSerialization) if (ForSerialization)
AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache)); AST->WriterData.reset(new ASTWriterData(*AST->ModCache));
// Zero out now to ease cleanup during crash recovery. // Zero out now to ease cleanup during crash recovery.
CI = nullptr; CI = nullptr;
Diags = nullptr; Diags = nullptr;
@ -2379,8 +2378,8 @@ bool ASTUnit::serialize(raw_ostream &OS) {
SmallString<128> Buffer; SmallString<128> Buffer;
llvm::BitstreamWriter Stream(Buffer); llvm::BitstreamWriter Stream(Buffer);
InMemoryModuleCache ModuleCache; IntrusiveRefCntPtr<ModuleCache> ModCache = createCrossProcessModuleCache();
ASTWriter Writer(Stream, Buffer, ModuleCache, {}); ASTWriter Writer(Stream, Buffer, *ModCache, {});
return serializeUnit(Writer, Buffer, getSema(), OS); return serializeUnit(Writer, Buffer, getSema(), OS);
} }

View File

@ -39,16 +39,17 @@
#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/Config/llvm-config.h" #include "llvm/Config/llvm-config.h"
#include "llvm/Support/AdvisoryLock.h"
#include "llvm/Support/BuryPointer.h" #include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Errc.h" #include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/Program.h" #include "llvm/Support/Program.h"
@ -66,11 +67,10 @@ using namespace clang;
CompilerInstance::CompilerInstance( CompilerInstance::CompilerInstance(
std::shared_ptr<PCHContainerOperations> PCHContainerOps, std::shared_ptr<PCHContainerOperations> PCHContainerOps,
InMemoryModuleCache *SharedModuleCache) ModuleCache *ModCache)
: ModuleLoader(/* BuildingModule = */ SharedModuleCache), : ModuleLoader(/*BuildingModule=*/ModCache),
Invocation(new CompilerInvocation()), Invocation(new CompilerInvocation()),
ModuleCache(SharedModuleCache ? SharedModuleCache ModCache(ModCache ? ModCache : createCrossProcessModuleCache()),
: new InMemoryModuleCache),
ThePCHContainerOperations(std::move(PCHContainerOps)) {} ThePCHContainerOperations(std::move(PCHContainerOps)) {}
CompilerInstance::~CompilerInstance() { CompilerInstance::~CompilerInstance() {
@ -205,7 +205,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::getASTReader() const {
return TheASTReader; return TheASTReader;
} }
void CompilerInstance::setASTReader(IntrusiveRefCntPtr<ASTReader> Reader) { void CompilerInstance::setASTReader(IntrusiveRefCntPtr<ASTReader> Reader) {
assert(ModuleCache.get() == &Reader->getModuleManager().getModuleCache() && assert(ModCache.get() == &Reader->getModuleManager().getModuleCache() &&
"Expected ASTReader to use the same PCM cache"); "Expected ASTReader to use the same PCM cache");
TheASTReader = std::move(Reader); TheASTReader = std::move(Reader);
} }
@ -625,9 +625,8 @@ void CompilerInstance::createPCHExternalASTSource(
IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
StringRef Path, StringRef Sysroot, StringRef Path, StringRef Sysroot,
DisableValidationForModuleKind DisableValidation, DisableValidationForModuleKind DisableValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache,
InMemoryModuleCache &ModuleCache, ASTContext &Context, ASTContext &Context, const PCHContainerReader &PCHContainerRdr,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener, void *DeserializationListener, bool OwnDeserializationListener,
@ -635,7 +634,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader( IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
PP, ModuleCache, &Context, PCHContainerRdr, Extensions, PP, ModCache, &Context, PCHContainerRdr, Extensions,
Sysroot.empty() ? "" : Sysroot.data(), DisableValidation, Sysroot.empty() ? "" : Sysroot.data(), DisableValidation,
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false, AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
HSOpts.ModulesValidateSystemHeaders, HSOpts.ValidateASTInputFilesContent, HSOpts.ModulesValidateSystemHeaders, HSOpts.ValidateASTInputFilesContent,
@ -1166,7 +1165,8 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
// Never compile a module that's already finalized - this would cause the // Never compile a module that's already finalized - this would cause the
// existing module to be freed, causing crashes if it is later referenced // existing module to be freed, causing crashes if it is later referenced
if (ImportingInstance.getModuleCache().isPCMFinal(ModuleFileName)) { if (ImportingInstance.getModuleCache().getInMemoryModuleCache().isPCMFinal(
ModuleFileName)) {
ImportingInstance.getDiagnostics().Report( ImportingInstance.getDiagnostics().Report(
ImportLoc, diag::err_module_rebuild_finalized) ImportLoc, diag::err_module_rebuild_finalized)
<< ModuleName; << ModuleName;
@ -1477,15 +1477,13 @@ static bool compileModuleAndReadASTBehindLock(
Diags.Report(ModuleNameLoc, diag::remark_module_lock) Diags.Report(ModuleNameLoc, diag::remark_module_lock)
<< ModuleFileName << Module->Name; << ModuleFileName << Module->Name;
// FIXME: have LockFileManager return an error_code so that we can auto &ModuleCache = ImportingInstance.getModuleCache();
// avoid the mkdir when the directory already exists. ModuleCache.prepareForGetLock(ModuleFileName);
StringRef Dir = llvm::sys::path::parent_path(ModuleFileName);
llvm::sys::fs::create_directories(Dir);
while (true) { while (true) {
llvm::LockFileManager Lock(ModuleFileName); auto Lock = ModuleCache.getLock(ModuleFileName);
bool Owned; bool Owned;
if (llvm::Error Err = Lock.tryLock().moveInto(Owned)) { if (llvm::Error Err = Lock->tryLock().moveInto(Owned)) {
// ModuleCache takes care of correctness and locks are only necessary for // ModuleCache takes care of correctness and locks are only necessary for
// performance. Fallback to building the module in case of any lock // performance. Fallback to building the module in case of any lock
// related errors. // related errors.
@ -1502,19 +1500,19 @@ static bool compileModuleAndReadASTBehindLock(
// Someone else is responsible for building the module. Wait for them to // Someone else is responsible for building the module. Wait for them to
// finish. // finish.
switch (Lock.waitForUnlockFor(std::chrono::seconds(90))) { switch (Lock->waitForUnlockFor(std::chrono::seconds(90))) {
case llvm::WaitForUnlockResult::Success: case llvm::WaitForUnlockResult::Success:
break; // The interesting case. break; // The interesting case.
case llvm::WaitForUnlockResult::OwnerDied: case llvm::WaitForUnlockResult::OwnerDied:
continue; // try again to get the lock. continue; // try again to get the lock.
case llvm::WaitForUnlockResult::Timeout: case llvm::WaitForUnlockResult::Timeout:
// Since ModuleCache takes care of correctness, we try waiting for // Since the InMemoryModuleCache takes care of correctness, we try waiting
// another process to complete the build so clang does not do it done // for someone else to complete the build so that it does not happen
// twice. If case of timeout, build it ourselves. // twice. In case of timeout, build it ourselves.
Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout) Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout)
<< Module->Name; << Module->Name;
// Clear the lock file so that future invocations can make progress. // Clear the lock file so that future invocations can make progress.
Lock.unsafeMaybeUnlock(); Lock->unsafeMaybeUnlock();
continue; continue;
} }

View File

@ -292,10 +292,9 @@ private:
class PrecompilePreambleConsumer : public PCHGenerator { class PrecompilePreambleConsumer : public PCHGenerator {
public: public:
PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP, PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP,
InMemoryModuleCache &ModuleCache, ModuleCache &ModCache, StringRef isysroot,
StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer) std::shared_ptr<PCHBuffer> Buffer)
: PCHGenerator(PP, ModuleCache, "", isysroot, std::move(Buffer), : PCHGenerator(PP, ModCache, "", isysroot, std::move(Buffer),
ArrayRef<std::shared_ptr<ModuleFileExtension>>(), ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
/*AllowASTWithErrors=*/true), /*AllowASTWithErrors=*/true),
Action(Action) {} Action(Action) {}

View File

@ -90,6 +90,7 @@
#include "clang/Serialization/ContinuousRangeMap.h" #include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/ModuleFile.h" #include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/ModuleFileExtension.h" #include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/ModuleManager.h" #include "clang/Serialization/ModuleManager.h"
@ -3318,9 +3319,12 @@ ASTReader::ReadControlBlock(ModuleFile &F,
StoredSignature, Capabilities); StoredSignature, Capabilities);
// If we diagnosed a problem, produce a backtrace. // If we diagnosed a problem, produce a backtrace.
bool recompilingFinalized = bool recompilingFinalized = Result == OutOfDate &&
Result == OutOfDate && (Capabilities & ARR_OutOfDate) && (Capabilities & ARR_OutOfDate) &&
getModuleManager().getModuleCache().isPCMFinal(F.FileName); getModuleManager()
.getModuleCache()
.getInMemoryModuleCache()
.isPCMFinal(F.FileName);
if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized) if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized)
Diag(diag::note_module_file_imported_by) Diag(diag::note_module_file_imported_by)
<< F.FileName << !F.ModuleName.empty() << F.ModuleName; << F.FileName << !F.ModuleName.empty() << F.ModuleName;
@ -5006,7 +5010,7 @@ ASTReader::ReadASTCore(StringRef FileName,
bool ShouldFinalizePCM = false; bool ShouldFinalizePCM = false;
auto FinalizeOrDropPCM = llvm::make_scope_exit([&]() { auto FinalizeOrDropPCM = llvm::make_scope_exit([&]() {
auto &MC = getModuleManager().getModuleCache(); auto &MC = getModuleManager().getModuleCache().getInMemoryModuleCache();
if (ShouldFinalizePCM) if (ShouldFinalizePCM)
MC.finalizePCM(FileName); MC.finalizePCM(FileName);
else else
@ -5143,7 +5147,8 @@ ASTReader::readUnhashedControlBlock(ModuleFile &F, bool WasImportedBy,
// validation will fail during the as-system import since the PCM on disk // validation will fail during the as-system import since the PCM on disk
// doesn't guarantee that -Werror was respected. However, the -Werror // doesn't guarantee that -Werror was respected. However, the -Werror
// flags were checked during the initial as-user import. // flags were checked during the initial as-user import.
if (getModuleManager().getModuleCache().isPCMFinal(F.FileName)) { if (getModuleManager().getModuleCache().getInMemoryModuleCache().isPCMFinal(
F.FileName)) {
Diag(diag::warn_module_system_bit_conflict) << F.FileName; Diag(diag::warn_module_system_bit_conflict) << F.FileName;
return Success; return Success;
} }
@ -5651,14 +5656,14 @@ namespace {
} // namespace } // namespace
bool ASTReader::readASTFileControlBlock( bool ASTReader::readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr, StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
const InMemoryModuleCache &ModuleCache,
const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
ASTReaderListener &Listener, bool ValidateDiagnosticOptions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions,
unsigned ClientLoadCapabilities) { unsigned ClientLoadCapabilities) {
// Open the AST file. // Open the AST file.
std::unique_ptr<llvm::MemoryBuffer> OwnedBuffer; std::unique_ptr<llvm::MemoryBuffer> OwnedBuffer;
llvm::MemoryBuffer *Buffer = ModuleCache.lookupPCM(Filename); llvm::MemoryBuffer *Buffer =
ModCache.getInMemoryModuleCache().lookupPCM(Filename);
if (!Buffer) { if (!Buffer) {
// FIXME: We should add the pcm to the InMemoryModuleCache if it could be // FIXME: We should add the pcm to the InMemoryModuleCache if it could be
// read again later, but we do not have the context here to determine if it // read again later, but we do not have the context here to determine if it
@ -5947,19 +5952,15 @@ bool ASTReader::readASTFileControlBlock(
return false; return false;
} }
bool ASTReader::isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, bool ASTReader::isAcceptableASTFile(
const InMemoryModuleCache &ModuleCache, StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts,
const LangOptions &LangOpts, const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts,
const TargetOptions &TargetOpts, StringRef ExistingModuleCachePath, bool RequireStrictOptionMatches) {
const PreprocessorOptions &PPOpts,
StringRef ExistingModuleCachePath,
bool RequireStrictOptionMatches) {
SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts,
ExistingModuleCachePath, FileMgr, ExistingModuleCachePath, FileMgr,
RequireStrictOptionMatches); RequireStrictOptionMatches);
return !readASTFileControlBlock(Filename, FileMgr, ModuleCache, return !readASTFileControlBlock(Filename, FileMgr, ModCache, PCHContainerRdr,
PCHContainerRdr,
/*FindModuleFileExtensions=*/false, validator, /*FindModuleFileExtensions=*/false, validator,
/*ValidateDiagnosticOptions=*/true); /*ValidateDiagnosticOptions=*/true);
} }
@ -6496,7 +6497,10 @@ ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const {
bool ASTReader::canRecoverFromOutOfDate(StringRef ModuleFileName, bool ASTReader::canRecoverFromOutOfDate(StringRef ModuleFileName,
unsigned int ClientLoadCapabilities) { unsigned int ClientLoadCapabilities) {
return ClientLoadCapabilities & ARR_OutOfDate && return ClientLoadCapabilities & ARR_OutOfDate &&
!getModuleManager().getModuleCache().isPCMFinal(ModuleFileName); !getModuleManager()
.getModuleCache()
.getInMemoryModuleCache()
.isPCMFinal(ModuleFileName);
} }
llvm::iterator_range<ASTReader::ModuleDeclIterator> llvm::iterator_range<ASTReader::ModuleDeclIterator>
@ -10862,7 +10866,7 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) {
} }
} }
ASTReader::ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache, ASTReader::ASTReader(Preprocessor &PP, ModuleCache &ModCache,
ASTContext *Context, ASTContext *Context,
const PCHContainerReader &PCHContainerRdr, const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
@ -10878,7 +10882,7 @@ ASTReader::ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()), PCHContainerRdr(PCHContainerRdr), Diags(PP.getDiagnostics()),
StackHandler(Diags), PP(PP), ContextObj(Context), StackHandler(Diags), PP(PP), ContextObj(Context),
ModuleMgr(PP.getFileManager(), ModuleCache, PCHContainerRdr, ModuleMgr(PP.getFileManager(), ModCache, PCHContainerRdr,
PP.getHeaderSearchInfo()), PP.getHeaderSearchInfo()),
DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot), DummyIdResolver(PP), ReadTimer(std::move(ReadTimer)), isysroot(isysroot),
DisableValidationKind(DisableValidationKind), DisableValidationKind(DisableValidationKind),

View File

@ -75,6 +75,7 @@
#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTRecordWriter.h" #include "clang/Serialization/ASTRecordWriter.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/ModuleFile.h" #include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/ModuleFileExtension.h" #include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/SerializationDiagnostic.h" #include "clang/Serialization/SerializationDiagnostic.h"
@ -5326,12 +5327,11 @@ void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
} }
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream, ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
SmallVectorImpl<char> &Buffer, SmallVectorImpl<char> &Buffer, ModuleCache &ModCache,
InMemoryModuleCache &ModuleCache,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps, bool BuildingImplicitModule, bool IncludeTimestamps, bool BuildingImplicitModule,
bool GeneratingReducedBMI) bool GeneratingReducedBMI)
: Stream(Stream), Buffer(Buffer), ModuleCache(ModuleCache), : Stream(Stream), Buffer(Buffer), ModCache(ModCache),
IncludeTimestamps(IncludeTimestamps), IncludeTimestamps(IncludeTimestamps),
BuildingImplicitModule(BuildingImplicitModule), BuildingImplicitModule(BuildingImplicitModule),
GeneratingReducedBMI(GeneratingReducedBMI) { GeneratingReducedBMI(GeneratingReducedBMI) {
@ -5389,9 +5389,9 @@ ASTWriter::WriteAST(llvm::PointerUnion<Sema *, Preprocessor *> Subject,
if (ShouldCacheASTInMemory) { if (ShouldCacheASTInMemory) {
// Construct MemoryBuffer and update buffer manager. // Construct MemoryBuffer and update buffer manager.
ModuleCache.addBuiltPCM(OutputFile, ModCache.getInMemoryModuleCache().addBuiltPCM(
llvm::MemoryBuffer::getMemBufferCopy( OutputFile, llvm::MemoryBuffer::getMemBufferCopy(
StringRef(Buffer.begin(), Buffer.size()))); StringRef(Buffer.begin(), Buffer.size())));
} }
return Signature; return Signature;
} }

View File

@ -18,6 +18,7 @@ add_clang_library(clangSerialization
GeneratePCH.cpp GeneratePCH.cpp
GlobalModuleIndex.cpp GlobalModuleIndex.cpp
InMemoryModuleCache.cpp InMemoryModuleCache.cpp
ModuleCache.cpp
ModuleFile.cpp ModuleFile.cpp
ModuleFileExtension.cpp ModuleFileExtension.cpp
ModuleManager.cpp ModuleManager.cpp

View File

@ -23,7 +23,7 @@
using namespace clang; using namespace clang;
PCHGenerator::PCHGenerator( PCHGenerator::PCHGenerator(
Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile,
StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors, bool IncludeTimestamps, bool AllowASTWithErrors, bool IncludeTimestamps,
@ -31,7 +31,7 @@ PCHGenerator::PCHGenerator(
bool GeneratingReducedBMI) bool GeneratingReducedBMI)
: PP(PP), Subject(&PP), OutputFile(OutputFile), isysroot(isysroot.str()), : PP(PP), Subject(&PP), OutputFile(OutputFile), isysroot(isysroot.str()),
Buffer(std::move(Buffer)), Stream(this->Buffer->Data), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
Writer(Stream, this->Buffer->Data, ModuleCache, Extensions, Writer(Stream, this->Buffer->Data, ModCache, Extensions,
IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI), IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI),
AllowASTWithErrors(AllowASTWithErrors), AllowASTWithErrors(AllowASTWithErrors),
ShouldCacheASTInMemory(ShouldCacheASTInMemory) { ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
@ -100,12 +100,12 @@ ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
void PCHGenerator::anchor() {} void PCHGenerator::anchor() {}
CXX20ModulesGenerator::CXX20ModulesGenerator(Preprocessor &PP, CXX20ModulesGenerator::CXX20ModulesGenerator(Preprocessor &PP,
InMemoryModuleCache &ModuleCache, ModuleCache &ModCache,
StringRef OutputFile, StringRef OutputFile,
bool GeneratingReducedBMI, bool GeneratingReducedBMI,
bool AllowASTWithErrors) bool AllowASTWithErrors)
: PCHGenerator( : PCHGenerator(
PP, ModuleCache, OutputFile, llvm::StringRef(), PP, ModCache, OutputFile, llvm::StringRef(),
std::make_shared<PCHBuffer>(), std::make_shared<PCHBuffer>(),
/*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(), /*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
AllowASTWithErrors, /*IncludeTimestamps=*/false, AllowASTWithErrors, /*IncludeTimestamps=*/false,

View File

@ -0,0 +1,44 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/InMemoryModuleCache.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/Path.h"
using namespace clang;
namespace {
class CrossProcessModuleCache : public ModuleCache {
InMemoryModuleCache InMemory;
public:
void prepareForGetLock(StringRef ModuleFilename) override {
// FIXME: Do this in LockFileManager and only if the directory doesn't
// exist.
StringRef Dir = llvm::sys::path::parent_path(ModuleFilename);
llvm::sys::fs::create_directories(Dir);
}
std::unique_ptr<llvm::AdvisoryLock>
getLock(StringRef ModuleFilename) override {
return std::make_unique<llvm::LockFileManager>(ModuleFilename);
}
InMemoryModuleCache &getInMemoryModuleCache() override { return InMemory; }
const InMemoryModuleCache &getInMemoryModuleCache() const override {
return InMemory;
}
};
} // namespace
IntrusiveRefCntPtr<ModuleCache> clang::createCrossProcessModuleCache() {
return llvm::makeIntrusiveRefCnt<CrossProcessModuleCache>();
}

View File

@ -18,6 +18,7 @@
#include "clang/Lex/ModuleMap.h" #include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/ModuleFile.h" #include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/PCHContainerOperations.h" #include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
@ -182,17 +183,20 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// Load the contents of the module // Load the contents of the module
if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) { if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us. // The buffer was already provided for us.
NewModule->Buffer = &ModuleCache->addBuiltPCM(FileName, std::move(Buffer)); NewModule->Buffer = &getModuleCache().getInMemoryModuleCache().addBuiltPCM(
FileName, std::move(Buffer));
// Since the cached buffer is reused, it is safe to close the file // Since the cached buffer is reused, it is safe to close the file
// descriptor that was opened while stat()ing the PCM in // descriptor that was opened while stat()ing the PCM in
// lookupModuleFile() above, it won't be needed any longer. // lookupModuleFile() above, it won't be needed any longer.
Entry->closeFile(); Entry->closeFile();
} else if (llvm::MemoryBuffer *Buffer = } else if (llvm::MemoryBuffer *Buffer =
getModuleCache().lookupPCM(FileName)) { getModuleCache().getInMemoryModuleCache().lookupPCM(
FileName)) {
NewModule->Buffer = Buffer; NewModule->Buffer = Buffer;
// As above, the file descriptor is no longer needed. // As above, the file descriptor is no longer needed.
Entry->closeFile(); Entry->closeFile();
} else if (getModuleCache().shouldBuildPCM(FileName)) { } else if (getModuleCache().getInMemoryModuleCache().shouldBuildPCM(
FileName)) {
// Report that the module is out of date, since we tried (and failed) to // Report that the module is out of date, since we tried (and failed) to
// import it earlier. // import it earlier.
Entry->closeFile(); Entry->closeFile();
@ -213,7 +217,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return Missing; return Missing;
} }
NewModule->Buffer = &getModuleCache().addPCM(FileName, std::move(*Buf)); NewModule->Buffer = &getModuleCache().getInMemoryModuleCache().addPCM(
FileName, std::move(*Buf));
} }
// Initialize the stream. // Initialize the stream.
@ -324,12 +329,11 @@ void ModuleManager::moduleFileAccepted(ModuleFile *MF) {
ModulesInCommonWithGlobalIndex.push_back(MF); ModulesInCommonWithGlobalIndex.push_back(MF);
} }
ModuleManager::ModuleManager(FileManager &FileMgr, ModuleManager::ModuleManager(FileManager &FileMgr, ModuleCache &ModCache,
InMemoryModuleCache &ModuleCache,
const PCHContainerReader &PCHContainerRdr, const PCHContainerReader &PCHContainerRdr,
const HeaderSearch &HeaderSearchInfo) const HeaderSearch &HeaderSearchInfo)
: FileMgr(FileMgr), ModuleCache(&ModuleCache), : FileMgr(FileMgr), ModCache(&ModCache), PCHContainerRdr(PCHContainerRdr),
PCHContainerRdr(PCHContainerRdr), HeaderSearchInfo(HeaderSearchInfo) {} HeaderSearchInfo(HeaderSearchInfo) {}
void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor, void ModuleManager::visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) { llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit) {

View File

@ -18,6 +18,7 @@
#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/Sema.h" #include "clang/Sema/Sema.h"
#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/VirtualFileSystem.h"
@ -287,10 +288,12 @@ TEST(GeneratePCHFrontendAction, CacheGeneratedPCH) {
// Check whether the PCH was cached. // Check whether the PCH was cached.
if (ShouldCache) if (ShouldCache)
EXPECT_EQ(InMemoryModuleCache::Final, EXPECT_EQ(InMemoryModuleCache::Final,
Compiler.getModuleCache().getPCMState(PCHFilename)); Compiler.getModuleCache().getInMemoryModuleCache().getPCMState(
PCHFilename));
else else
EXPECT_EQ(InMemoryModuleCache::Unknown, EXPECT_EQ(InMemoryModuleCache::Unknown,
Compiler.getModuleCache().getPCMState(PCHFilename)); Compiler.getModuleCache().getInMemoryModuleCache().getPCMState(
PCHFilename));
} }
} }

View File

@ -16,7 +16,6 @@
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetOptions.h"
#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Serialization/InMemoryModuleCache.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <memory> #include <memory>