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"
43 std::atomic<const std::optional<DependencyDirectivesTy> *>
DepDirectives;
65 : MaybeStat(
std::move(Stat)), Contents(
nullptr) {
72 : MaybeStat(
std::move(Stat)), Contents(
std::move(Contents)) {
77 bool isError()
const {
return !MaybeStat; }
85 assert(!MaybeStat->isDirectory() &&
"not a file");
86 assert(Contents &&
"contents not initialized");
87 return Contents->Original->getBuffer();
92 std::optional<ArrayRef<dependency_directives_scan::Directive>>
96 assert(Contents &&
"contents not initialized");
97 if (
auto *Directives = Contents->DepDirectives.load()) {
98 if (Directives->has_value())
105 std::error_code
getError()
const {
return MaybeStat.getError(); }
110 assert(MaybeStat->getName().empty() &&
"stat name must be empty");
117 return MaybeStat->getUniqueID();
128 void clearStatName() {
130 MaybeStat = llvm::vfs::Status::copyWithNewName(*MaybeStat,
"");
135 llvm::ErrorOr<llvm::vfs::Status> MaybeStat;
142 CachedFileContents *Contents;
161 std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
162 llvm::BumpPtrAllocator>
166 llvm::DenseMap<llvm::sys::fs::UniqueID, const CachedFileSystemEntry *>
190 llvm::ErrorOr<llvm::vfs::Status> Stat);
197 std::unique_ptr<llvm::MemoryBuffer> Contents);
214 llvm::ErrorOr<StringRef> RealPath);
233 std::variant<NegativelyCachedInfo, SizeChangedInfo>
Info;
249 std::vector<OutOfDateEntry>
253 std::unique_ptr<CacheShard[]> CacheShards;
261 std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
262 llvm::BumpPtrAllocator>
268 assert(llvm::sys::path::is_absolute_gnu(Filename));
269 auto It = Cache.find(Filename);
270 return It == Cache.end() ?
nullptr : It->getValue().first;
278 assert(llvm::sys::path::is_absolute_gnu(Filename));
279 auto [It, Inserted] = Cache.insert({Filename, {&Entry,
nullptr}});
284 assert((!CachedEntry &&
CachedRealPath) &&
"entry already present");
285 CachedEntry = &Entry;
293 assert(llvm::sys::path::is_absolute_gnu(Filename));
294 auto It = Cache.find(Filename);
295 return It == Cache.end() ?
nullptr : It->getValue().second;
303 assert(llvm::sys::path::is_absolute_gnu(Filename));
304 auto [It, Inserted] = Cache.insert({Filename, {
nullptr, &RealPath}});
309 assert((!
CachedRealPath && CachedEntry) &&
"real path already present");
321 std::string Filename;
330 : Filename(Name), Entry(Entry) {}
333 llvm::vfs::Status Stat = Entry.getStatus();
334 if (!Stat.isDirectory())
335 Stat = llvm::vfs::Status::copyWithNewSize(Stat,
getContents().size());
336 return llvm::vfs::Status::copyWithNewName(Stat, Filename);
339 bool isError()
const {
return Entry.isError(); }
345 return Entry.getError();
349 StringRef
getContents()
const {
return Entry.getOriginalContents(); }
351 std::optional<ArrayRef<dependency_directives_scan::Directive>>
353 return Entry.getDirectiveTokens();
367 :
public llvm::RTTIExtends<DependencyScanningWorkerFilesystem,
368 llvm::vfs::ProxyFileSystem> {
370 static const char ID;
376 llvm::ErrorOr<llvm::vfs::Status>
status(
const Twine &Path)
override;
377 llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
405 std::optional<ArrayRef<dependency_directives_scan::Directive>>
409 return Entry->getDirectiveTokens();
415 bool exists(
const Twine &Path)
override;
423 llvm::ErrorOr<const CachedFileSystemEntry &>
424 computeAndStoreResult(StringRef OriginalFilename,
425 StringRef FilenameForLookup);
429 struct TentativeEntry {
430 llvm::vfs::Status Status;
431 std::unique_ptr<llvm::MemoryBuffer> Contents;
433 TentativeEntry(llvm::vfs::Status Status,
434 std::unique_ptr<llvm::MemoryBuffer> Contents =
nullptr)
435 : Status(
std::move(Status)), Contents(
std::move(Contents)) {}
440 llvm::ErrorOr<TentativeEntry> readFile(StringRef Filename);
445 const CachedFileSystemEntry &
446 getOrEmplaceSharedEntryForUID(TentativeEntry TEntry);
453 const CachedFileSystemEntry *
454 findEntryByFilenameWithWriteThrough(StringRef Filename);
458 const CachedFileSystemEntry *
459 findSharedEntryByUID(llvm::vfs::Status Stat)
const {
466 const CachedFileSystemEntry &
467 insertLocalEntryForFilename(StringRef Filename,
468 const CachedFileSystemEntry &Entry) {
469 return LocalCache.insertEntryForFilename(Filename, Entry);
475 const CachedFileSystemEntry &
476 getOrEmplaceSharedEntryForFilename(StringRef Filename, std::error_code EC) {
477 return SharedCache.getShardForFilename(Filename)
478 .getOrEmplaceEntryForFilename(Filename, EC);
484 const CachedFileSystemEntry &
485 getOrInsertSharedEntryForFilename(StringRef Filename,
486 const CachedFileSystemEntry &Entry) {
487 return SharedCache.getShardForFilename(Filename)
488 .getOrInsertEntryForFilename(Filename, Entry);
491 void printImpl(raw_ostream &OS, PrintType
Type,
494 OS <<
"DependencyScanningFilesystem\n";
500 bool shouldBypass(StringRef Path)
const;
503 DependencyScanningFilesystemSharedCache &SharedCache;
506 DependencyScanningFilesystemLocalCache LocalCache;
509 std::optional<std::string> BypassedPathPrefix;
513 llvm::ErrorOr<std::string> WorkingDirForCacheLookup;
515 void updateWorkingDirForCacheLookup();
517 llvm::ErrorOr<StringRef>
518 tryGetFilenameForLookup(StringRef OriginalFilename,
519 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
This class is a local cache, that caches the 'stat' and 'open' calls to the underlying real file syst...
const CachedRealPath & insertRealPathForFilename(StringRef Filename, const CachedRealPath &RealPath)
Associates the given real path with the filename and returns the given entry pointer (for convenience...
const CachedFileSystemEntry & insertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry)
Associates the given entry with the filename and returns the given entry pointer (for convenience).
const CachedFileSystemEntry * findEntryByFilename(StringRef Filename) const
Returns entry associated with the filename or nullptr if none is found.
const CachedRealPath * findRealPathByFilename(StringRef Filename) const
Returns real path associated with the filename or nullptr if none is found.
This class is a shared cache, that caches the 'stat' and 'open' calls to the underlying real file sys...
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()
std::optional< ArrayRef< dependency_directives_scan::Directive > > getDirectiveTokens(const Twine &Path)
void setBypassedPathPrefix(StringRef Prefix)
Set the prefix for paths that should bypass this VFS and go straight to the underlying VFS.
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.
void resetBypassedPathPrefix()
Make it so that no paths bypass this VFS.
bool exists(const Twine &Path) override
Check whether Path exists.
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
DependencyScanningWorkerFilesystem(DependencyScanningFilesystemSharedCache &SharedCache, IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
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
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
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',...
@ Type
The name was classified as a type.
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)
const CachedFileSystemEntry & getOrEmplaceEntryForUID(llvm::sys::fs::UniqueID UID, llvm::vfs::Status Stat, std::unique_ptr< llvm::MemoryBuffer > Contents)
Returns entry associated with the unique ID if there is some.
llvm::SpecificBumpPtrAllocator< CachedFileSystemEntry > EntryStorage
The backing storage for cached entries.
llvm::SpecificBumpPtrAllocator< CachedFileContents > ContentsStorage
The backing storage for cached contents.
llvm::SpecificBumpPtrAllocator< CachedRealPath > RealPathStorage
The backing storage for cached real paths.
const CachedFileSystemEntry * findEntryByUID(llvm::sys::fs::UniqueID UID) const
Returns entry associated with the unique ID or nullptr if none is found.
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.
const CachedFileSystemEntry & getOrInsertEntryForFilename(StringRef Filename, const CachedFileSystemEntry &Entry)
Returns entry associated with the filename if there is some.
const CachedFileSystemEntry * findEntryByFilename(StringRef Filename) const
Returns entry associated with the filename or nullptr if none is found.
const CachedFileSystemEntry & getOrEmplaceEntryForFilename(StringRef Filename, llvm::ErrorOr< llvm::vfs::Status > Stat)
Returns entry associated with the filename if there is some.
llvm::StringMap< std::pair< const CachedFileSystemEntry *, const CachedRealPath * >, llvm::BumpPtrAllocator > CacheByFilename
Map from filenames to cached entries and real paths.
const CachedRealPath & getOrEmplaceRealPathForFilename(StringRef Filename, llvm::ErrorOr< StringRef > RealPath)
Returns the real path associated with the filename if there is some.
llvm::DenseMap< llvm::sys::fs::UniqueID, const CachedFileSystemEntry * > EntriesByUID
Map from unique IDs to cached entries.
OutOfDateEntry(const char *Path)
std::variant< NegativelyCachedInfo, SizeChangedInfo > Info
OutOfDateEntry(const char *Path, uint64_t CachedSize, uint64_t ActualSize)