Skip to content

🍒 [clang][deps] Implement efficient in-process ModuleCache #10471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: swift/release/6.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clang/include/clang/Frontend/ASTUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class FileManager;
class FrontendAction;
class HeaderSearch;
class InputKind;
class InMemoryModuleCache;
class ModuleCache;
class PCHContainerOperations;
class PCHContainerReader;
class Preprocessor;
Expand Down Expand Up @@ -110,7 +110,7 @@ class ASTUnit {
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
IntrusiveRefCntPtr<FileManager> FileMgr;
IntrusiveRefCntPtr<SourceManager> SourceMgr;
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;
IntrusiveRefCntPtr<ModuleCache> ModCache;
std::unique_ptr<HeaderSearch> HeaderInfo;
IntrusiveRefCntPtr<TargetInfo> Target;
std::shared_ptr<Preprocessor> PP;
Expand Down
13 changes: 6 additions & 7 deletions clang/include/clang/Frontend/CompilerInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class DiagnosticsEngine;
class DiagnosticConsumer;
class FileManager;
class FrontendAction;
class InMemoryModuleCache;
class Module;
class ModuleCache;
class Preprocessor;
class Sema;
class SourceManager;
Expand Down Expand Up @@ -115,7 +115,7 @@ class CompilerInstance : public ModuleLoader {
IntrusiveRefCntPtr<SourceManager> SourceMgr;

/// The cache of PCM files.
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;
IntrusiveRefCntPtr<ModuleCache> ModCache;

/// The preprocessor.
std::shared_ptr<Preprocessor> PP;
Expand Down Expand Up @@ -223,7 +223,7 @@ class CompilerInstance : public ModuleLoader {
explicit CompilerInstance(
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>(),
InMemoryModuleCache *SharedModuleCache = nullptr);
ModuleCache *ModCache = nullptr);
~CompilerInstance() override;

/// @name High-Level Operations
Expand Down Expand Up @@ -793,9 +793,8 @@ class CompilerInstance : public ModuleLoader {
static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
StringRef Path, StringRef Sysroot,
DisableValidationForModuleKind DisableValidation,
bool AllowPCHWithCompilerErrors, Preprocessor &PP,
InMemoryModuleCache &ModuleCache, ASTContext &Context,
const PCHContainerReader &PCHContainerRdr,
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ModuleCache &ModCache,
ASTContext &Context, const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
void *DeserializationListener, bool OwnDeserializationListener,
Expand Down Expand Up @@ -966,7 +965,7 @@ class CompilerInstance : public ModuleLoader {
bool addCachedModuleFile(StringRef Path, StringRef CacheKey,
StringRef Provider);

InMemoryModuleCache &getModuleCache() const { return *ModuleCache; }
ModuleCache &getModuleCache() const { return *ModCache; }
};

} // end namespace clang
Expand Down
11 changes: 5 additions & 6 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ struct HeaderFileInfo;
class HeaderSearchOptions;
class LangOptions;
class MacroInfo;
class InMemoryModuleCache;
class ModuleCache;
class NamedDecl;
class NamespaceDecl;
class ObjCCategoryDecl;
Expand Down Expand Up @@ -1641,8 +1641,8 @@ class ASTReader
///
/// \param ReadTimer If non-null, a timer used to track the time spent
/// deserializing.
ASTReader(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
ASTContext *Context, const PCHContainerReader &PCHContainerRdr,
ASTReader(Preprocessor &PP, ModuleCache &ModCache, ASTContext *Context,
const PCHContainerReader &PCHContainerRdr,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
StringRef isysroot = "",
DisableValidationForModuleKind DisableValidationKind =
Expand Down Expand Up @@ -1853,8 +1853,7 @@ class ASTReader
///
/// \returns true if an error occurred, false otherwise.
static bool readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr,
const InMemoryModuleCache &ModuleCache,
StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions,
ASTReaderListener &Listener, bool ValidateDiagnosticOptions,
unsigned ClientLoadCapabilities = ARR_ConfigurationMismatch |
Expand All @@ -1863,7 +1862,7 @@ class ASTReader
/// Determine whether the given AST file is acceptable to load into a
/// translation unit with the given language and target options.
static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
const InMemoryModuleCache &ModuleCache,
const ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr,
const LangOptions &LangOpts,
const TargetOptions &TargetOpts,
Expand Down
21 changes: 10 additions & 11 deletions clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class LangOptions;
class MacroDefinitionRecord;
class MacroInfo;
class Module;
class InMemoryModuleCache;
class ModuleCache;
class ModuleFileExtension;
class ModuleFileExtensionWriter;
class NamedDecl;
Expand Down Expand Up @@ -117,7 +117,7 @@ class ASTWriter : public ASTDeserializationListener,
const SmallVectorImpl<char> &Buffer;

/// The PCM manager which manages memory buffers for pcm files.
InMemoryModuleCache &ModuleCache;
ModuleCache &ModCache;

/// The preprocessor we're writing.
Preprocessor *PP = nullptr;
Expand Down Expand Up @@ -638,7 +638,7 @@ class ASTWriter : public ASTDeserializationListener,
/// Create a new precompiled header writer that outputs to
/// the given bitstream.
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
InMemoryModuleCache &ModuleCache,
ModuleCache &ModCache,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
bool GeneratingReducedBMI = false);
Expand Down Expand Up @@ -940,9 +940,8 @@ class PCHGenerator : public SemaConsumer {
virtual Module *getEmittingModule(ASTContext &Ctx);

public:
PCHGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
StringRef OutputFile, StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
PCHGenerator(Preprocessor &PP, ModuleCache &ModCache, StringRef OutputFile,
StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
bool BuildingImplicitModule = false,
Expand All @@ -964,13 +963,13 @@ class CXX20ModulesGenerator : public PCHGenerator {
protected:
virtual Module *getEmittingModule(ASTContext &Ctx) override;

CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
StringRef OutputFile, bool GeneratingReducedBMI);

public:
CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
CXX20ModulesGenerator(Preprocessor &PP, ModuleCache &ModCache,
StringRef OutputFile)
: CXX20ModulesGenerator(PP, ModuleCache, OutputFile,
: CXX20ModulesGenerator(PP, ModCache, OutputFile,
/*GeneratingReducedBMI=*/false) {}

void HandleTranslationUnit(ASTContext &Ctx) override;
Expand All @@ -980,9 +979,9 @@ class ReducedBMIGenerator : public CXX20ModulesGenerator {
void anchor() override;

public:
ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
ReducedBMIGenerator(Preprocessor &PP, ModuleCache &ModCache,
StringRef OutputFile)
: CXX20ModulesGenerator(PP, ModuleCache, OutputFile,
: CXX20ModulesGenerator(PP, ModCache, OutputFile,
/*GeneratingReducedBMI=*/true) {}
};

Expand Down
50 changes: 50 additions & 0 deletions clang/include/clang/Serialization/ModuleCache.h
Original file line number Diff line number Diff line change
@@ -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
12 changes: 6 additions & 6 deletions clang/include/clang/Serialization/ModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class FileEntry;
class FileManager;
class GlobalModuleIndex;
class HeaderSearch;
class InMemoryModuleCache;
class ModuleCache;
class PCHContainerReader;

namespace serialization {
Expand Down Expand Up @@ -65,7 +65,7 @@ class ModuleManager {
FileManager &FileMgr;

/// Cache of PCM files.
IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache;
IntrusiveRefCntPtr<ModuleCache> ModCache;

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

explicit ModuleManager(FileManager &FileMgr, InMemoryModuleCache &ModuleCache,
const PCHContainerReader &PCHContainerRdr,
const HeaderSearch &HeaderSearchInfo);
ModuleManager(FileManager &FileMgr, ModuleCache &ModCache,
const PCHContainerReader &PCHContainerRdr,
const HeaderSearch &HeaderSearchInfo);

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

InMemoryModuleCache &getModuleCache() const { return *ModuleCache; }
ModuleCache &getModuleCache() const { return *ModCache; }
};

} // namespace serialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "clang/CAS/CASOptions.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningCASFilesystem.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/CAS/ActionCache.h"

Expand Down Expand Up @@ -123,14 +124,16 @@ class DependencyScanningService {

bool useCASFS() const { return (bool)SharedFS; }

ModuleCacheMutexes &getModuleCacheMutexes() { return ModCacheMutexes; }

private:
const ScanningMode Mode;
const ScanningOutputFormat Format;
CASOptions CASOpts;
std::shared_ptr<llvm::cas::ObjectStore> CAS;
std::shared_ptr<llvm::cas::ActionCache> Cache;
/// Whether to optimize the modules' command-line arguments.
const ScanningOptimizations OptimizeArgs;
ScanningOptimizations OptimizeArgs;
/// Whether to set up command-lines to load PCM files eagerly.
const bool EagerLoadModules;
/// Whether to trace VFS accesses.
Expand All @@ -140,6 +143,8 @@ class DependencyScanningService {
IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem> SharedFS;
/// The global file system cache.
std::optional<DependencyScanningFilesystemSharedCache> SharedCache;
/// The global module cache mutexes.
ModuleCacheMutexes ModCacheMutexes;
};

} // end namespace dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ struct P1689Rule {
class DependencyScanningTool {
public:
/// Construct a dependency scanning tool.
///
/// @param Service The parent service. Must outlive the tool.
/// @param FS The filesystem for the tool to use. Defaults to the physical FS.
DependencyScanningTool(DependencyScanningService &Service,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
llvm::vfs::createPhysicalFileSystem());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ class DependencyActionController {
/// using the regular processing run.
class DependencyScanningWorker {
public:
/// Construct a dependency scanning worker.
///
/// @param Service The parent service. Must outlive the worker.
/// @param FS The filesystem for the worker to use.
DependencyScanningWorker(DependencyScanningService &Service,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);

Expand Down Expand Up @@ -149,7 +153,7 @@ class DependencyScanningWorker {
DependencyActionController &Controller, DiagnosticConsumer &DiagsConsumer,
raw_ostream *VerboseOS, bool DiagGenerationAsCompilation);

ScanningOutputFormat getScanningFormat() const { return Format; }
ScanningOutputFormat getScanningFormat() const { return Service.getFormat(); }

CachingOnDiskFileSystemPtr getCASFS() { return CacheFS; }
const CASOptions &getCASOpts() const { return CASOpts; }
Expand All @@ -160,11 +164,11 @@ class DependencyScanningWorker {
/// each invocation.
llvm::IntrusiveRefCntPtr<FileManager> getOrCreateFileManager() const;

bool shouldEagerLoadModules() const { return EagerLoadModules; }

llvm::vfs::FileSystem &getVFS() const { return *BaseFS; }

private:
/// The parent dependency scanning service.
DependencyScanningService &Service;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
/// The file system to be used during the scan.
/// This is either \c FS passed in the constructor (when performing canonical
Expand All @@ -174,11 +178,6 @@ class DependencyScanningWorker {
/// dependency-directives-extracting) filesystem overlaid on top of \c FS
/// (passed in the constructor).
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
ScanningOutputFormat Format;
/// Whether to optimize the modules' command-line arguments.
ScanningOptimizations OptimizeArgs;
/// Whether to set up command-lines to load PCM files eagerly.
bool EagerLoadModules;

/// The caching file system.
CachingOnDiskFileSystemPtr CacheFS;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===----------------------------------------------------------------------===//
//
// 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_TOOLING_DEPENDENCYSCANNING_INPROCESSMODULECACHE_H
#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_INPROCESSMODULECACHE_H

#include "clang/Serialization/ModuleCache.h"
#include "llvm/ADT/StringMap.h"

#include <mutex>
#include <shared_mutex>

namespace clang {
namespace tooling {
namespace dependencies {
struct ModuleCacheMutexes {
std::mutex Mutex;
llvm::StringMap<std::unique_ptr<std::shared_mutex>> Map;
};

IntrusiveRefCntPtr<ModuleCache>
makeInProcessModuleCache(ModuleCacheMutexes &Mutexes);
} // namespace dependencies
} // namespace tooling
} // namespace clang

#endif
Loading