9#ifndef LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNINGFILESYSTEM_H
10#define LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNINGFILESYSTEM_H
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/StringMap.h"
16#include "llvm/Support/Allocator.h"
17#include "llvm/Support/ErrorOr.h"
18#include "llvm/Support/VirtualFileSystem.h"
19#include <condition_variable>
47 std::atomic<const std::optional<DependencyDirectivesTy> *>
DepDirectives;
69 : MaybeStat(
std::move(Stat)), Contents(
nullptr) {
76 : MaybeStat(
std::move(Stat)), Contents(
std::move(Contents)) {
81 bool isError()
const {
return !MaybeStat; }
89 assert(!MaybeStat->isDirectory() &&
"not a file");
90 assert(Contents &&
"contents not initialized");
91 return Contents->Original->getBuffer();
96 std::optional<ArrayRef<dependency_directives_scan::Directive>>
100 assert(Contents &&
"contents not initialized");
101 if (
auto *Directives = Contents->DepDirectives.load()) {
102 if (Directives->has_value())
109 std::error_code
getError()
const {
return MaybeStat.getError(); }
114 assert(MaybeStat->getName().empty() &&
"stat name must be empty");
121 return MaybeStat->getUniqueID();
132 void clearStatName() {
134 MaybeStat = llvm::vfs::Status::copyWithNewName(*MaybeStat,
"");
139 llvm::ErrorOr<llvm::vfs::Status> MaybeStat;
146 CachedFileContents *Contents;
168 llvm::ErrorOr<const CachedFileSystemEntry *>
Result = std::error_code{};
171 void publish(llvm::ErrorOr<const CachedFileSystemEntry *> R) {
173 std::lock_guard<std::mutex> EntryLock(
Mutex);
174 assert(!
Done &&
"slot already published");
225 llvm::ErrorOr<StringRef> RealPath);
244 std::variant<NegativelyCachedInfo, SizeChangedInfo>
Info;
260 std::vector<OutOfDateEntry>
264 std::unique_ptr<CacheShard[]> CacheShards;
273 std::string Filename;
282 : Filename(Name), Entry(Entry) {}
285 llvm::vfs::Status Stat = Entry.getStatus();
286 if (!Stat.isDirectory())
287 Stat = llvm::vfs::Status::copyWithNewSize(Stat,
getContents().size());
288 return llvm::vfs::Status::copyWithNewName(Stat, Filename);
291 bool isError()
const {
return Entry.isError(); }
297 return Entry.getError();
301 StringRef
getContents()
const {
return Entry.getOriginalContents(); }
303 std::optional<ArrayRef<dependency_directives_scan::Directive>>
305 return Entry.getDirectiveTokens();
319 :
public llvm::RTTIExtends<DependencyScanningWorkerFilesystem,
320 llvm::vfs::ProxyFileSystem> {
322 static const char ID;
328 llvm::ErrorOr<llvm::vfs::Status>
status(
const Twine &Path)
override;
329 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
351 std::optional<ArrayRef<dependency_directives_scan::Directive>>
355 return Entry->getDirectiveTokens();
361 bool exists(
const Twine &Path)
override;
370 llvm::ErrorOr<const CachedFileSystemEntry *>
371 resolveFilenameThroughSharedCache(StringRef OriginalFilename,
372 StringRef FilenameForLookup);
379 resolveUIDThroughSharedCache(StringRef OriginalFilename,
380 const llvm::vfs::Status &Stat);
384 struct TentativeEntry {
385 llvm::vfs::Status Status;
386 std::unique_ptr<llvm::MemoryBuffer> Contents;
388 TentativeEntry(llvm::vfs::Status Status,
389 std::unique_ptr<llvm::MemoryBuffer> Contents =
nullptr)
390 : Status(
std::move(Status)), Contents(
std::move(Contents)) {}
395 llvm::ErrorOr<TentativeEntry> readFile(StringRef Filename);
397 void printImpl(raw_ostream &OS, PrintType Type,
400 OS <<
"DependencyScanningFilesystem\n";
401 getUnderlyingFS().print(OS, Type,
IndentLevel + 1);
405 DependencyScanningService &Service;
412 const CachedFileSystemEntry *File =
nullptr;
418 llvm::StringMap<LocalEntry, llvm::BumpPtrAllocator> LocalCache;
422 llvm::ErrorOr<std::string> WorkingDirForCacheLookup;
424 void updateWorkingDirForCacheLookup();
426 llvm::ErrorOr<StringRef>
427 tryGetFilenameForLookup(StringRef OriginalFilename,
428 llvm::SmallVectorImpl<char> &PathBuf)
const;
This is the interface for scanning header and source files to get the minimum necessary preprocessor ...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
An in-memory representation of a file system entity that is of interest to the dependency scanning fi...
llvm::sys::fs::UniqueID getUniqueID() const
CachedFileSystemEntry(llvm::ErrorOr< llvm::vfs::Status > Stat, CachedFileContents *Contents)
Creates an entry representing a file with contents.
StringRef getOriginalContents() const
CachedFileContents * getCachedContents() const
std::optional< ArrayRef< dependency_directives_scan::Directive > > getDirectiveTokens() const
CachedFileSystemEntry(llvm::ErrorOr< llvm::vfs::Status > Stat)
Creates an entry without contents: either a filesystem error or a directory with stat value.
llvm::vfs::Status getStatus() const
std::error_code getError() const
CacheShard & getShardForUID(llvm::sys::fs::UniqueID UID) const
CacheShard & getShardForFilename(StringRef Filename) const
Returns shard for the given key.
std::vector< OutOfDateEntry > getOutOfDateEntries(llvm::vfs::FileSystem &UnderlyingFS) const
Visits all cached entries and re-stat an entry using UnderlyingFS to check if the cache contains out-...
DependencyScanningFilesystemSharedCache()
The dependency scanning service contains shared configuration and state that is used by the individua...
std::optional< ArrayRef< dependency_directives_scan::Directive > > getDirectiveTokens(const Twine &Path)
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
bool ensureDirectiveTokensArePopulated(EntryRef Entry)
Ensure the directive tokens are populated for this file entry.
bool exists(const Twine &Path) override
Check whether Path exists.
DependencyScanningWorkerFilesystem(DependencyScanningService &Service, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
llvm::ErrorOr< EntryRef > getOrCreateFileSystemEntry(StringRef Filename)
Returns entry for the given filename.
llvm::ErrorOr< std::unique_ptr< llvm::vfs::File > > openFileForRead(const Twine &Path) override
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
llvm::ErrorOr< llvm::vfs::Status > status(const Twine &Path) override
Reference to a CachedFileSystemEntry.
llvm::vfs::Status getStatus() const
StringRef getContents() const
friend class DependencyScanningWorkerFilesystem
std::optional< ArrayRef< dependency_directives_scan::Directive > > getDirectiveTokens() const
llvm::ErrorOr< EntryRef > unwrapError() const
If the cached entry represents an error, promotes it into ErrorOr.
EntryRef(StringRef Name, const CachedFileSystemEntry &Entry)
SmallVector< dependency_directives_scan::Directive, 20 > DependencyDirectivesTy
llvm::ErrorOr< std::string > CachedRealPath
The JSON file list parser is used to communicate input to InstallAPI.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
Contents and directive tokens of a cached file entry.
std::unique_ptr< llvm::MemoryBuffer > Original
Owning storage for the original contents.
SmallVector< dependency_directives_scan::Token, 10 > DepDirectiveTokens
std::atomic< const std::optional< DependencyDirectivesTy > * > DepDirectives
Accessor to the directive tokens that's atomic to avoid data races.
std::mutex ValueLock
The mutex that must be locked before mutating directive tokens.
CachedFileContents(std::unique_ptr< llvm::MemoryBuffer > Contents)
Cache state per filename: resolved entry, real path, and an in-flight slot (if any).
const CachedFileSystemEntry * Entry
const CachedRealPath * RealPath
std::shared_ptr< InProgressEntry > InProgress
Cache state stored per unique ID; similar to FilenameCacheState.
const CachedFileSystemEntry * Entry
std::shared_ptr< InProgressEntry > InProgress
llvm::SpecificBumpPtrAllocator< CachedFileSystemEntry > EntryStorage
The backing storage for cached entries.
llvm::SpecificBumpPtrAllocator< CachedFileContents > ContentsStorage
The backing storage for cached contents.
llvm::StringMap< FilenameCacheState, llvm::BumpPtrAllocator > CacheByFilename
Map from filenames to their cached state.
llvm::SpecificBumpPtrAllocator< CachedRealPath > RealPathStorage
The backing storage for cached real paths.
const CachedRealPath * findRealPathByFilename(StringRef Filename) const
Returns the real path associated with the filename or nullptr if none is found.
std::mutex CacheLock
The mutex that needs to be locked before mutation of any member.
llvm::DenseMap< llvm::sys::fs::UniqueID, UIDCacheState > EntriesByUID
Map from unique IDs to their cached state.
const CachedRealPath & getOrEmplaceRealPathForFilename(StringRef Filename, llvm::ErrorOr< StringRef > RealPath)
Returns the real path associated with the filename if there is some.
In-flight slot used to dedup concurrent producers for the same key.
void publish(llvm::ErrorOr< const CachedFileSystemEntry * > R)
Publishes the producer's outcome to this slot and wakes all waiters.
llvm::ErrorOr< const CachedFileSystemEntry * > Result
std::condition_variable CondVar
OutOfDateEntry(const char *Path)
std::variant< NegativelyCachedInfo, SizeChangedInfo > Info
OutOfDateEntry(const char *Path, uint64_t CachedSize, uint64_t ActualSize)