14#ifndef LLVM_SUPPORT_VIRTUALFILESYSTEM_H
15#define LLVM_SUPPORT_VIRTUALFILESYSTEM_H
36#include <system_error>
82 const Twine &NewName);
84 const Twine &NewName);
125 if (
auto Status = status())
134 bool RequiresNullTerminator =
true,
bool IsVolatile =
false) = 0;
137 virtual std::error_code
close() = 0;
141 getWithPath(
ErrorOr<std::unique_ptr<File>> Result,
const Twine &
P);
182 std::shared_ptr<detail::DirIterImpl> Impl;
187 assert(Impl.get() !=
nullptr &&
"requires non-null implementation");
188 if (Impl->CurrentEntry.path().empty())
197 assert(Impl &&
"attempting to increment past end");
198 EC = Impl->increment();
199 if (Impl->CurrentEntry.path().empty())
208 if (Impl &&
RHS.Impl)
209 return Impl->CurrentEntry.path() ==
RHS.Impl->CurrentEntry.path();
210 return !Impl && !
RHS.Impl;
213 return !(*
this ==
RHS);
223 std::vector<directory_iterator>
Stack;
233 std::shared_ptr<detail::RecDirIterState>
238 std::error_code &EC);
250 return State ==
Other.State;
253 return !(*
this ==
RHS);
258 assert(!State->Stack.empty() &&
259 "Cannot get level without any iteration state");
260 return State->Stack.size() - 1;
263 void no_push() { State->HasNoPushRequest =
true; }
270 static const char ID;
287 return openFileForRead(Path);
295 getBufferForFile(
const Twine &
Name, int64_t FileSize = -1,
296 bool RequiresNullTerminator =
true,
bool IsVolatile =
false,
302 std::error_code &EC) = 0;
314 virtual std::error_code getRealPath(
const Twine &Path,
319 virtual bool exists(
const Twine &Path);
322 virtual std::error_code isLocal(
const Twine &Path,
bool &Result);
341 enum class PrintType { Summary, Contents, RecursiveContents };
343 unsigned IndentLevel = 0)
const {
351 visitChildFileSystems(Callback);
354#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
360 unsigned IndentLevel)
const {
361 printIndent(
OS, IndentLevel);
362 OS <<
"FileSystem\n";
366 for (
unsigned i = 0; i < IndentLevel; ++i)
394 :
public RTTIExtends<OverlayFileSystem, FileSystem> {
402 static const char ID;
409 bool exists(
const Twine &Path)
override;
411 openFileForRead(
const Twine &Path)
override;
414 std::error_code setCurrentWorkingDirectory(
const Twine &Path)
override;
415 std::error_code isLocal(
const Twine &Path,
bool &Result)
override;
416 std::error_code getRealPath(
const Twine &Path,
447 unsigned IndentLevel)
const override;
448 void visitChildFileSystems(VisitCallbackTy Callback)
override;
455 :
public RTTIExtends<ProxyFileSystem, FileSystem> {
457 static const char ID;
462 return FS->status(Path);
464 bool exists(
const Twine &Path)
override {
return FS->exists(Path); }
467 return FS->openFileForRead(Path);
470 return FS->dir_begin(Dir, EC);
473 return FS->getCurrentWorkingDirectory();
476 return FS->setCurrentWorkingDirectory(Path);
480 return FS->getRealPath(Path, Output);
483 return FS->isLocal(Path, Result);
491 FS->visitChildFileSystems(Callback);
498 virtual void anchor()
override;
503class InMemoryDirectory;
511 std::unique_ptr<llvm::MemoryBuffer>
Buffer;
532 explicit operator bool()
const {
return static_cast<bool>(
Value); }
533 operator std::error_code()
const {
return Value.getError(); }
542 :
public RTTIExtends<InMemoryFileSystem, FileSystem> {
543 std::unique_ptr<detail::InMemoryDirectory> Root;
544 std::string WorkingDirectory;
545 bool UseNormalizedPaths =
true;
548 static const char ID;
555 bool addFile(
const Twine &Path, time_t ModificationTime,
556 std::unique_ptr<llvm::MemoryBuffer> Buffer,
557 std::optional<uint32_t>
User, std::optional<uint32_t> Group,
558 std::optional<llvm::sys::fs::file_type>
Type,
559 std::optional<llvm::sys::fs::perms> Perms,
MakeNodeFn MakeNode);
565 size_t SymlinkDepth = 0)
const;
579 bool addFile(
const Twine &Path, time_t ModificationTime,
580 std::unique_ptr<llvm::MemoryBuffer> Buffer,
581 std::optional<uint32_t>
User = std::nullopt,
582 std::optional<uint32_t> Group = std::nullopt,
583 std::optional<llvm::sys::fs::file_type>
Type = std::nullopt,
584 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
604 static constexpr size_t MaxSymlinkDepth = 16;
611 time_t ModificationTime,
612 std::optional<uint32_t>
User = std::nullopt,
613 std::optional<uint32_t> Group = std::nullopt,
614 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
622 bool addFileNoOwn(
const Twine &Path, time_t ModificationTime,
624 std::optional<uint32_t>
User = std::nullopt,
625 std::optional<uint32_t> Group = std::nullopt,
626 std::optional<llvm::sys::fs::file_type>
Type = std::nullopt,
627 std::optional<llvm::sys::fs::perms> Perms = std::nullopt);
636 openFileForRead(
const Twine &Path)
override;
640 return WorkingDirectory;
648 std::error_code getRealPath(
const Twine &Path,
650 std::error_code isLocal(
const Twine &Path,
bool &Result)
override;
651 std::error_code setCurrentWorkingDirectory(
const Twine &Path)
override;
655 unsigned IndentLevel)
const override;
666 StringRef YAMLFilePath,
void *DiagContext =
nullptr,
670 template <
typename T1,
typename T2>
783 :
public RTTIExtends<RedirectingFileSystem, vfs::FileSystem> {
785 static const char ID;
787 enum NameKind { NK_NotSet, NK_External, NK_Virtual };
827 std::vector<std::unique_ptr<Entry>> Contents;
844 Contents.push_back(std::move(
Content));
860 std::string ExternalContentsPath;
866 :
Entry(K,
Name), ExternalContentsPath(ExternalContentsPath),
874 return UseName == NK_NotSet ? GlobalUseExternalName
875 : (UseName == NK_External);
881 switch (
E->getKind()) {
882 case EK_DirectoryRemap:
899 :
RemapEntry(EK_DirectoryRemap,
Name, ExternalContentsPath, UseName) {}
902 return E->getKind() == EK_DirectoryRemap;
927 std::optional<std::string> ExternalRedirect;
937 if (isa<DirectoryRemapEntry>(
E))
939 if (
auto *FE = dyn_cast<FileEntry>(
E))
940 return FE->getExternalContentsPath();
962 const Twine &OriginalPath)
const;
987 return (lhs ==
"/" && rhs ==
"\\") || (lhs ==
"\\" && rhs ==
"/");
991 std::vector<std::unique_ptr<Entry>> Roots;
994 std::string WorkingDirectory;
1003 std::string OverlayFileDir;
1011 bool CaseSensitive = is_style_posix(sys::path::Style::native);
1015 bool IsRelativeOverlay =
false;
1019 bool UseExternalNames =
true;
1023 mutable bool HasBeenUsed =
false;
1026 bool UsageTrackingActive =
false;
1030 RedirectKind Redirection = RedirectKind::Fallthrough;
1034 RootRelativeKind RootRelative = RootRelativeKind::CWD;
1054 const LookupResult &Result);
1064 static std::unique_ptr<RedirectingFileSystem>
1065 create(std::unique_ptr<MemoryBuffer> Buffer,
1070 static std::unique_ptr<RedirectingFileSystem>
1071 create(
ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
1075 bool exists(
const Twine &Path)
override;
1078 std::error_code getRealPath(
const Twine &Path,
1083 std::error_code setCurrentWorkingDirectory(
const Twine &Path)
override;
1085 std::error_code isLocal(
const Twine &Path,
bool &Result)
override;
1091 void setOverlayFileDir(
StringRef PrefixDir);
1097 void setFallthrough(
bool Fallthrough);
1101 std::vector<llvm::StringRef> getRoots()
const;
1108 void printEntry(
raw_ostream &
OS, Entry *
E,
unsigned IndentLevel = 0)
const;
1112 unsigned IndentLevel)
const override;
1113 void visitChildFileSystems(VisitCallbackTy Callback)
override;
1120 std::unique_ptr<llvm::MemoryBuffer> Buffer,
1123 void *DiagContext =
nullptr,
1127 std::vector<YAMLVFSEntry> Mappings;
1128 std::optional<bool> IsCaseSensitive;
1129 std::optional<bool> IsOverlayRelative;
1130 std::optional<bool> UseExternalNames;
1131 std::string OverlayDir;
1142 IsCaseSensitive = CaseSensitive;
1148 IsOverlayRelative =
true;
1149 OverlayDir.assign(OverlayDirectory.
str());
1152 const std::vector<YAMLVFSEntry> &
getMappings()
const {
return Mappings; }
1165 std::size_t NumStatusCalls = 0;
1166 std::size_t NumOpenFileForReadCalls = 0;
1167 std::size_t NumDirBeginCalls = 0;
1168 std::size_t NumGetRealPathCalls = 0;
1169 std::size_t NumExistsCalls = 0;
1170 std::size_t NumIsLocalCalls = 0;
1177 return ProxyFileSystem::status(Path);
1181 ++NumOpenFileForReadCalls;
1182 return ProxyFileSystem::openFileForRead(Path);
1187 return ProxyFileSystem::dir_begin(Dir, EC);
1192 ++NumGetRealPathCalls;
1193 return ProxyFileSystem::getRealPath(Path, Output);
1198 return ProxyFileSystem::exists(Path);
1203 return ProxyFileSystem::isLocal(Path, Result);
1208 unsigned IndentLevel)
const override;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Provides ErrorOr<T> smart pointer.
static void makeAbsolute(SmallVectorImpl< char > &Path)
Make Path absolute.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
static const char * toString(MIToken::TokenKind TokenKind)
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)
This file defines the SmallVector class.
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents either an error or a value T.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
Inheritance utility for extensible RTTI.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reverse_iterator rbegin()
std::reverse_iterator< const_iterator > const_reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
bool equals_insensitive(StringRef RHS) const
Check for string equality, ignoring case.
Target - Wrapper for Target specific information.
A thread-safe version of RefCountedBase.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Represents the result of a call to sys::fs::status().
The virtual file system interface.
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForReadBinary(const Twine &Path)
Get a File object for the binary file at Path, if one exists.
virtual std::error_code setCurrentWorkingDirectory(const Twine &Path)=0
Set the working directory.
virtual void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the text file at Path, if one exists.
virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC)=0
Get a directory_iterator for Dir.
void printIndent(raw_ostream &OS, unsigned IndentLevel) const
void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const
virtual void visitChildFileSystems(VisitCallbackTy Callback)
void visit(VisitCallbackTy Callback)
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
virtual llvm::ErrorOr< Status > status()=0
Get the status of the file.
virtual llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBuffer(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)=0
Get the contents of the file as a MemoryBuffer.
virtual llvm::ErrorOr< std::string > getName()
Get the name of the file.
virtual void setPath(const Twine &Path)
virtual ~File()
Destroy the file after closing it (if open).
virtual std::error_code close()=0
Closes the file.
Adaptor from InMemoryDir::iterator to directory_iterator.
An in-memory file system.
~InMemoryFileSystem() override
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
A file system that allows overlaying one AbstractFileSystem on top of another.
const_iterator overlays_end() const
const_iterator overlays_begin() const
reverse_iterator overlays_rbegin()
Get an iterator pointing to the least recently added file system.
const_range overlays_range() const
const_reverse_iterator overlays_rend() const
reverse_iterator overlays_rend()
Get an iterator pointing one-past the most recently added file system.
FileSystemList::const_reverse_iterator const_iterator
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
const_reverse_iterator overlays_rbegin() const
FileSystemList::reverse_iterator iterator
By default, this delegates all calls to the underlying file system.
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
void visitChildFileSystems(VisitCallbackTy Callback) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
llvm::ErrorOr< Status > status(const Twine &Path) override
bool exists(const Twine &Path) override
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
std::error_code isLocal(const Twine &Path, bool &Result) override
ProxyFileSystem(IntrusiveRefCntPtr< FileSystem > FS)
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
FileSystem & getUnderlyingFS() const
Directory iterator implementation for RedirectingFileSystem's directory entries.
A helper class to hold the common YAML parsing state.
A directory in the vfs with explicitly specified contents.
iterator contents_begin()
static bool classof(const Entry *E)
DirectoryEntry(StringRef Name, Status S)
Constructs an empty directory entry.
DirectoryEntry(StringRef Name, std::vector< std::unique_ptr< Entry > > Contents, Status S)
Constructs a directory entry with explicitly specified contents.
decltype(Contents)::iterator iterator
void addContent(std::unique_ptr< Entry > Content)
Entry * getLastContent() const
A directory in the vfs that maps to a directory in the external file system.
DirectoryRemapEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
static bool classof(const Entry *E)
A single file or directory in the VFS.
StringRef getName() const
EntryKind getKind() const
Entry(EntryKind K, StringRef Name)
A file in the vfs that maps to a file in the external file system.
static bool classof(const Entry *E)
FileEntry(StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
A file or directory in the vfs that is mapped to a file or directory in the external filesystem.
StringRef getExternalContentsPath() const
NameKind getUseName() const
RemapEntry(EntryKind K, StringRef Name, StringRef ExternalContentsPath, NameKind UseName)
bool useExternalName(bool GlobalUseExternalName) const
Whether to use the external path as the name for this file or directory.
static bool classof(const Entry *E)
A virtual file system parsed from a YAML file.
void setUsageTrackingActive(bool Active)
RootRelativeKind
The type of relative path used by Roots.
RedirectKind
The type of redirection to perform.
The result of a status operation.
llvm::sys::fs::perms getPermissions() const
llvm::sys::fs::UniqueID getUniqueID() const
LLVM_ABI bool equivalent(const Status &Other) const
static LLVM_ABI Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
LLVM_ABI Status(const Twine &Name, llvm::sys::fs::UniqueID UID, llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, uint64_t Size, llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms)
LLVM_ABI bool isStatusKnown() const
LLVM_ABI bool exists() const
bool ExposesExternalVFSPath
Whether this entity has an external path different from the virtual path, and the external path is ex...
uint32_t getGroup() const
static LLVM_ABI Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
LLVM_ABI bool isOther() const
LLVM_ABI bool isSymlink() const
llvm::sys::TimePoint getLastModificationTime() const
llvm::sys::fs::file_type getType() const
LLVM_ABI bool isRegularFile() const
LLVM_ABI bool isDirectory() const
StringRef getName() const
Returns the name that should be used for this file or directory.
File system that tracks the number of calls to the underlying file system.
bool exists(const Twine &Path) override
TracingFileSystem(llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
ErrorOr< Status > status(const Twine &Path) override
std::error_code isLocal(const Twine &Path, bool &Result) override
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
LLVM_ABI void addFileMapping(StringRef VirtualPath, StringRef RealPath)
void setCaseSensitivity(bool CaseSensitive)
void setOverlayDir(StringRef OverlayDirectory)
const std::vector< YAMLVFSEntry > & getMappings() const
LLVM_ABI void write(llvm::raw_ostream &OS)
LLVM_ABI void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
void setUseExternalNames(bool UseExtNames)
The in memory file system is a tree of Nodes.
std::error_code getError() const
NamedNodeOrError(std::error_code EC)
const detail::InMemoryNode * operator*() const
StringRef getName() const
NamedNodeOrError(llvm::errc EC)
NamedNodeOrError(llvm::SmallString< 128 > Name, const detail::InMemoryNode *Node)
A member of a directory, yielded by a directory_iterator.
directory_entry()=default
directory_entry(std::string Path, llvm::sys::fs::file_type Type)
llvm::StringRef path() const
llvm::sys::fs::file_type type() const
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
directory_iterator(std::shared_ptr< detail::DirIterImpl > I)
bool operator==(const directory_iterator &RHS) const
const directory_entry * operator->() const
const directory_entry & operator*() const
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
bool operator!=(const directory_iterator &RHS) const
directory_iterator()=default
Construct an 'end' iterator.
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
const directory_entry & operator*() const
recursive_directory_iterator()=default
Construct an 'end' iterator.
bool operator!=(const recursive_directory_iterator &RHS) const
bool operator==(const recursive_directory_iterator &Other) const
int level() const
Gets the current level. Starting path is at level 0.
LLVM_ABI recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
const directory_entry * operator->() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
file_type
An enumeration for the file system's view of the type.
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
LLVM_ABI std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
LLVM_ABI llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
LLVM_ABI void collectVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Collect all pairs of <virtual path, real path> entries from the YAMLFilePath.
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
LLVM_ABI std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto reverse(ContainerTy &&C)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
Represents the result of a path lookup into the RedirectingFileSystem.
std::optional< StringRef > getExternalRedirect() const
If the found Entry maps the input path to a path in the external file system (i.e.
Entry * E
The entry the looked-up path corresponds to.
llvm::SmallVector< Entry *, 32 > Parents
Chain of parent directory entries for E.
YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory=false)
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
virtual std::error_code increment()=0
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
directory_entry CurrentEntry
LLVM_ABI Status makeStatus() const
llvm::sys::fs::file_type Type
std::unique_ptr< llvm::MemoryBuffer > Buffer
llvm::sys::fs::perms Perms
llvm::sys::fs::UniqueID DirUID
Keeps state for the recursive_directory_iterator.
std::vector< directory_iterator > Stack